题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5399
题意:求满足f1(f2(...(fm(i))...))=i的未知的函数有多少种可能。
解法:已经膜得如此明显了。。答案是(n!)^(m-1),m为-1的个数,因为m个不确定的函数,其中的m-1个固定了,那么还有一个也就固定了。每个不确定的都有n!种方案。
如果m为0,则有0种或者1种方案。也就是要看当前的一层一层能否推到f1(f2(...(fm(i))...))=i。要注意:当某个f里1..n没有全部出现时,即有重复数字时,答案是0。这个题要特殊考虑的情况超级多,要特别小心。
#include <bits/stdc++.h>
using namespace std;
//ans = (n!)^(m-1)
typedef long long LL;
const LL mod = 1e9+7;
LL qsm(LL a, LL n)
{
LL ret = 1;
while(n)
{
if(n&1) ret=ret*a%mod;
a = a*a%mod;
n>>=1;
}
return ret;
}
LL fac[110], f[110][110], cur[110];
int n, m;
int main()
{
fac[0] = 1;
for(int i=1; i<=100; i++)
{
fac[i] = fac[i-1]*i%mod;
}
while(~scanf("%d %d", &n,&m))
{
LL cnt = 0;
LL ans = 1;
for(int i=1; i<=m; i++)
{
scanf("%lld", &f[i][1]);
if(f[i][1]==-1)
{
cnt++;
}
else
{
for(int j=2; j<=n; j++)
{
scanf("%lld", &f[i][j]);
if(ans)
{
for(int k = 1; k<j; k++)
{
if(f[i][k]==f[i][j])
{
ans=0;
}
}
}
}
}
}
if(ans == 1)
{
if(cnt == 0)
{
for(int i=1; i<=n; i++) cur[i]=i;
for(int i=m; i>=1; i--)
{
for(int j=1; j<=n; j++)
{
cur[j]=f[i][cur[j]];
}
}
for(int i=1; i<=n; i++)
{
if(cur[i]!=i)
{
ans=0;
break;
}
}
}
else
{
ans = qsm(fac[n], cnt-1);
}
}
if(ans < 0) ans+=mod;
printf("%lld\n", ans);
}
return 0;
}