hdu5399

来源:互联网 发布:硬盘数据恢复最好软件 编辑:程序博客网 时间:2024/05/21 09:08

根据题意可知,要满足题意给的那个合成函数,每一个函数f[i] 与{1,2, ···, n} 都必须是双射关系,即不存在f[i][j] == f[i][k](j != k), 因此对于一个不确定的函数, 其可能的情况有n!个。如果用cnt 表示-1出现的次数, 那么如果cnt-1个未知函数确定了, 那么为了满足题目条件,剩下的未知函数是确定的。所以答案即为cnt-1个不确定函数的排列情况:(n!)^(cnt - 1)。另外对于cnt 等于0的情况,要验证是否满足题意。代码如下:

#include <iostream>#include <cstdio>#include <cstring>#include <cstdlib>#include <cmath>#include <algorithm>using namespace std;const int MAXN = 102;const int MOD = 1000000007;int f[MAXN][MAXN], n, m;bool che[MAXN];int solve(int cnt){    if(cnt == 1 || cnt == 0)    {        return 1;    }    long long  per = 1, ans = 1;    int i;    for(i = n; i >= 2; i--)    {        per = per * i % MOD;    }    for(i = 1; i <= cnt - 1; i++)    {        ans = ans * per % MOD;    }    return ans;}int main(){    while(scanf("%d%d", &n, &m) != -1)    {        int i, j, cnt = 0;        bool ok = true;        memset(f, -1, sizeof(f));        for(i = 1; i <= m; i++)        {            memset(che, false, sizeof(che));            for(j = 1; j <= n; j++)            {                scanf("%d", &f[i][j]);                if(f[i][j] == -1 && j == 1)                {                    cnt++;                    break;                }                che[f[i][j]] = true;            }            for(j = 1; f[i][1] != -1 && j <= n; j++)            {                if(che[j] == false)                {                    ok = false;                    break;                }            }        }        int tem, k;        for(k = 1; cnt == 0 && ok && k <= n; k++)        {            tem = f[m][k];            for(i = m-1; i >= 1; i--)            {                tem = f[i][tem];            }            if(tem != k)            {                ok = false;                break;            }        }        if(!ok)        {            printf("0\n");            continue;        }        printf("%d\n", solve(cnt));    }    return 0;}


0 0