标签:
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5399;
题意:
给你m个函数f1,f2,?,fm:{1,2,?,n}→{1,2,?,n}(即所有的x∈{1,2,?,n},对应的f(x)∈{1,2,?,n}),已知其中一部分函数的函数值,问你有多少种不同的组合使得所有的i(1≤i≤n),满足f1(f2(?fm(i)))=i
对于函数集f1,f2,?,fm and g1,g2,?,gm,当且仅当存在一个i(1≤i≤m),j(1≤j≤n),fi(j)≠gi(j),这样的组合才视为不同。其中输入-1表示f(x)可以等于任意一个值;
分析:
其实,仔细想想,你就会发现,此题的解跟-1的个数有关,当只有一个-1的时候,因为对应关系都已经决定了,所以只有1种可行解,而当你有两个-1时,其中一个函数的值可以根据另一个函数的改变而确定下来,故有n!种解。依此类推,当有k个-1时,(n!)^(k-1);
当然当k的值为0时有一种情况是输出1的要用dfs搞出来;
代码如下:
#include <iostream> #include <map> #include <cmath> #include <string.h> #include <cstdio> using namespace std; const int mod=1e9+7; long long f[150]; long long quick_mod(long long a,long long b){ long long ans=1; while(b){ if(b&1)ans=ans*a%mod; a=a*a%mod; b>>=1; } return ans; }//快速幂 int a[105][105]; bool vis[105]; int dfs(int t,int x) { if(t==1) return a[t][x]; return dfs(t-1,a[t][x]); }//dfs求解判断 int main(){ int n,m; f[1]=1; for(int i=2;i<150;i++) f[i]=f[i-1]*i%mod; while(scanf("%d%d",&n,&m)!=EOF){ int k=0; bool flag=false; for(int i=1;i<=m;){ int x; memset(vis,0,sizeof(vis)); for(int j=1;j<=n;j++){ scanf("%d",&x); if(x==-1){ k++; goto Next; } a[i][j]=x; vis[x]=true; } for(int j=1;j<=n;j++) if(vis[j]==false)flag=true; Next: i++; } if(flag==true){ cout<<0<<endl; } else if(k!=0){ cout<<quick_mod(f[n],k-1)<<endl; } else{ int i; for(i=1;i<=n;i++) if(dfs(m,i)!=i) break; if(i>n) puts("1"); else puts("0"); } } return 0; }
标签:
原文地址:http://blog.csdn.net/qq_27599517/article/details/51883893