Codecraft-17 and Codeforces Round #391 (Div. 1 + Div. 2, combined) C. Felicity is Coming!

来源:互联网 发布:福建随行软件下载 编辑:程序博客网 时间:2024/05/22 09:51

题目描述(点击打开链接):

简单来说就是,在n个gym,在第i个gym上有gi个物品,每个物品有一个类型。

有f(x)=y,可以将类型x的物品转化为类型y的物品。 问,有多少种f,可以让,每个gym上的物品在转换前和后,所有的物品种类数量没有变化。注意,所有物品都必须进行转换。

输入样例:      

2 42 1 23 2 3 4
2个gym会出现4中类型。

第一个gym上有2个物品,第一个物品的种类为1,第二个物品的种类为2。

第二个gym上有3个物品,第一个物品的种类为2,第二个物品的种类为3,第三个物品的种类为4。


solution:

f(1) = 1, f(2) = 2, f(3)=3, f(4) = 4   可以知道,该中的solution对于任意的一种情况都是符合的。所以,answer最少为一种。

f(1) = 1, f(2) = 2, f(3)=4, f(4) = 3。

找出solution的数量。
思路:总的来说,题目的思路还是比较简单的,就是要找出所有f(x)=y,其中在每个gym中,conut(x) == count(y)。

由于 n <=10^5, m <=10^6。 并不能开出一个二维的数组进行对每个gym的物品类型数量进行存储存储。就需要一些特别的办法来进行存储。这里用到了vector<vector<int>> s; or vector<int> s[MAX]; vector 数组进行存储。

关于vector进行排序的一些疑问:点击打开链接

这里一个好的解决办法就是:对物品的种类在哪个gym进行存储。这样存储的结果就是,对于具体的种类可以忽视。而,我们也知道,f的数量与具体的是哪个种类是无关的。

对于上面的例子:

type1: 1

type2: 1 2

type3: 2

type4: 2

排序的结果与存储结果恰好是一致的。

这样,我们就可以发现,type3 和 type4  是可以交换的。从而可以得出answer = 2;

Code:

#include <iostream>#include <algorithm>#include <vector>using namespace std;#define LL long longconst int MAX = 1e6 + 5;const LL MOD = 1e9 + 7;vector<int> arr[MAX];int n, m, x, y;LL fac[MAX];void init(){    fac[0] = 1; fac[1] = 1;    for(LL i = 2; i < MAX; ++ i){        fac[i] = (fac[i - 1] * i) % MOD;    }}void solve(){    cin >> n >> m;    // vector<vector<int> > arr(m);    for(int i = 0; i < n; ++ i){        cin >> x;        for(int j = 0; j < x; ++ j){            cin >> y;            arr[y - 1].push_back(i);        }    }    sort(arr, arr + m);    LL ans = 1;    int cnt = 1;    for(int i = 1; i < m; ++ i){        if(arr[i] == arr[i - 1])            cnt ++;        else {            ans = (ans * fac[cnt]) % MOD;            cnt = 1;        }    }    ans = (ans * fac[cnt]) % MOD;    cout << ans << endl;}int main(){    init();    solve();    return 0;}

关键点:

对于种类来说,如果种类作为“主轴”,那么对于任意两个类型可以交换就是其中的gym是一样的。(好吧,这句话还是特别抽象的。可以理解下。栗子就不举了。)

0 0
原创粉丝点击