多校第九场Too Simple题解

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5399

题意:给你m个映射,每个自变量x,对应一个f(x),这m个映射中有某一些已知的,给出你从1到n对应的映射值,剩下的一些不知道映射关系的,给你-1,要求找出符合条件的映射组合有多少组,其中要求是:对于i从1到n都满足f1(f2(……fm(i)))=i

思路:开个脑洞发现:如果-1的个数不止一个,那么只有最后一个-1所对应的映射是确定的,其他的都是任意的,如果-1的个数,只有一个,那么结果就是1,如果没有-1,那么还需要判断本身这个映射是不是满足条件。在做这些之前还需要考虑,这个映射是不是一一对应的,也就是这个映射是不是一个函数,只有这样才能继续讨论-1个数的问题,如果不是一一对应的,那么不同的i对应同样的f(i)就回不到i。

官方解释来一个帮助理解:首先要求每个f(i)是个排列,否则如果某个f(i)​将两个数映射向同一个数,那么最后这两个数得到的值一定相同。如果还剩一个位置为-1,那么这个排列是唯一确定的,假设,那么所以假设有c(c≥1)个-1,那么答案为(n!)^{c-1} 个可行的方案。

注意特判所有函数都已知的情况。

代码:

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define debug "output for debug\n"
#define pi (acos(-1.0))
#define eps (1e-8)
#define inf 0x3f3f3f3f
#define ll long long
using namespace std;
const int maxn = 100005;
int n, m;
int b[105][105];
const ll mod = 1e9 + 7;
ll a[105];
int check()
{
    int a[105];
    int f[105];
    for(int i=1;i<=n;i++)
        a[i]=i;
    for(int i=m; i>=1; i--)
    {
        for(int j=1; j<=n; j++)
            f[j]=b[i][a[j]];
        for(int j=1; j<=n; j++)
            a[j]=f[j];
    }
    for(int i=1;i<=n;i++)
    if(a[i]!=i)
      return 0;
    return 1;
}
int main () {
    a[0] = 1;
    for (int i = 1; i <= 100; i++)
        a[i] = i * a[i - 1] % mod;
    while(scanf("%d%d", &n, &m)!=EOF)
     {
        int k = 0;
       int flag = 0;
        for (int i = 1; i <= m; i++)
            {
            int sum[111] = {0};
            scanf("%d", &b[i][1]);
            if (b[i][1] == -1) {
                k++;
                continue;
            }
            sum[b[i][1]]++;
            for (int j = 2; j <= n; j++)
             {
                scanf("%d", &b[i][j]);
                sum[b[i][j]]++;
                if (sum[b[i][j]] > 1) flag = 1;
            }
        }
        if (flag) {
            printf("0\n");
            continue;
        }
        if (k == 0) {
            printf("%d\n", check());
            continue;
        }
        ll ans = 1;
        k--;
        while(k--) {
            ans = ans * a[n];
            ans %= mod;
        }
        printf("%I64d\n", ans);
    }
    return 0;
}

你可能感兴趣的:(多校,机智题)