Codecraft-17 and Codeforces Round #391

题目链接:http://codeforces.com/contest/757/problem/C

题意:给定n个gym和m个Pokemon的类型,然后给你每个gym内的Pokemon未进化之前的类型,问你存在多少种可行的进化方式。每种进化方式要满足进化后每个gym的类型和个数和进化后的每个gym的类型和个数都要一致。

思路:从Examples可以得到结论,对于类型x和类型y,只有当x在每个gym出现的个数与y在每个gym出现的个数相同时。类型x,y可以交换,即f(x)=y,f(y)=x是符合题目要求的,由于从gym入手解决问题比较苦难,并且进化之和两个类型有关,所以我们从类型入手。对于第i个gym的类型j,我们利用vector把i保存在j中。最后如果x,y的vector里的gym序列相同的话说明可以互相转换。 由于vector容器重载了<运算符和==运算符。所以可以很方面地进行判断。  最后就是计算共享了,其实就是个排列数的问题。

#define _CRT_SECURE_NO_DEPRECATE
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<stdio.h>
#include<queue>
#include<vector>
#include<stack>
#include<map>
#include<set>
#include<time.h>
#include<cmath>
using namespace std;
typedef long long int LL;
const int MAXN = 1e6 + 10;
const int mod = 1e9 + 7;
vector<int>G[MAXN];
int main(){
//#ifdef kirito
//    freopen("in.txt", "r", stdin);
//    freopen("out.txt", "w", stdout);
//#endif
//    int start = clock();
    int n,m,k,num;
    while (~scanf("%d%d", &n,&m)){
        for (int i = 0; i <= m; i++){
            G[i].clear();
        }
        for (int i = 1; i <= n; i++){
            scanf("%d",&k);
            for (int j = 1; j <= k; j++){
                scanf("%d", &num);
                G[num].push_back(i);
            }
        }
        sort(G + 1, G + m + 1);
        LL ans = 1,cnt=1;
        for (int i = 2; i <= m; i++){
            if (G[i] == G[i - 1]){
                cnt++;
                ans = (1LL*ans*cnt)%mod;
            }
            else{
                cnt = 1;
            }
        }
        printf("%I64d
", ans);
    }
//#ifdef LOCAL_TIME
//    cout << "[Finished in " << clock() - start << " ms]" << endl;
//#endif
    return 0;
}
原文地址:https://www.cnblogs.com/kirito520/p/6322839.html