HDU 5399 Too Simple(过程中略微用了一下dfs)——多校练习9
Too Simple
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Problem Description
Rhason Cheung had a simple problem, and asked Teacher Mai for help. But Teacher Mai thought this problem was too simple, sometimes naive. So she ask you for help.
Teacher Mai hasm functions f1,f2,⋯,fm:{1,2,⋯,n}→{1,2,⋯,n} (that
means for all x∈{1,2,⋯,n},f(x)∈{1,2,⋯,n} ).
But Rhason only knows some of these functions, and others are unknown.
She wants to know how many different function seriesf1,f2,⋯,fm there
are that for every i(1≤i≤n) ,f1(f2(⋯fm(i)))=i .
Two function series f1,f2,⋯,fm and g1,g2,⋯,gm are
considered different if and only if there exist i(1≤i≤m),j(1≤j≤n) ,fi(j)≠gi(j) .
Teacher Mai has
She wants to know how many different function series
Input
For each test case, the first lines contains two numbers n,m(1≤n,m≤100) .
The following arem lines.
In i -th
line, there is one number −1 or n space-separated
numbers.
If there is only one number−1 ,
the function fi is
unknown. Otherwise the j -th
number in the i -th
line means fi(j) .
The following are
If there is only one number
Output
For each test case print the answer modulo 109+7 .
Sample Input
3 3 1 2 3 -1 3 2 1
Sample Output
1HintThe order in the function series is determined. What she can do is to assign the values to the unknown functions.
题意:给你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),这种组合才视为不同。
假设还是不理解的话,我们来解释一下例子,3 3
1 2 3
-1
3 2 1
例子写成函数的形式就是
n=3,m=3
f1(1)=1,f1(2)=2,f1(3)=3
f2(1)、f2(2)、f2(3)的值均未知
f3(1)=3,f3(2)=2,f3(3)=1
所以要使全部的i(1≤i≤n),满足f1(f2(⋯fm(i)))=i。仅仅有一种组合情况,即f2(1)=3,f2(2)=2,f2(3)=1这么一种情况
解题思路:事实上。细致想想。你就会发现,此题的解跟-1的个数有关,当仅仅有一个-1的时候,由于相应关系都已经决定了。所以仅仅有1种可行解,而当你有两个-1时,当中一个函数的值能够依据还有一个函数的改变而确定下来,故有n!种解。
依此类推,当有k个-1时,解为
所以,我们仅仅须要提前将n!
计算好取模存下来。剩下的就是套公式了
有一点须要提醒的是,当-1的个数为0时。即不存在-1的情况,解并不一定为0,若不存在-1的情况下仍满足对于全部的i(1≤i≤n),满足f1(f2(⋯fm(i)))=i,输出1。否则输出0。所以加个dfs推断一下方案是否可行。多校的时候就被这一点坑了。看来还是考虑得不够多。
若对上述有什么不理解的地方,欢迎提出。
#pragma comment(linker, "/STACK:1024000000,1024000000") #include<stdio.h> #include<string.h> #include<stdlib.h> #include<queue> #include<math.h> #include<vector> #include<map> #include<set> #include<stdlib.h> #include<cmath> #include<string> #include<algorithm> #include<iostream> #define exp 1e-10 using namespace std; const int N = 105; const int inf = 1000000000; const int mod = 1000000007; __int64 s[N]; bool v[N]; int w[N][N]; int dfs(int t,int x) { if(t==1) return w[t][x]; return dfs(t-1,w[t][x]); } int main() { int n,m,i,j,k,x; bool flag; __int64 ans; s[0]=1; for(i=1;i<N;i++) s[i]=(s[i-1]*i)%mod; while(~scanf("%d%d",&n,&m)) { flag=true; for(k=0,i=1;i<=m;i++) { scanf("%d",&x); if(x==-1) k++; else { memset(v,false,sizeof(v)); v[x]=true;w[i][1]=x; for(j=2;j<=n;j++) { scanf("%d",&x); v[x]=true; w[i][j]=x; } for(j=1;j<=n;j++) if(!v[j]) break; if(j<=n) flag=false; } } /*for(i=1;i<=m;i++) { for(j=1;j<=n;j++) printf("%d ",w[i][j]); printf("\n"); }*/ if(!flag) puts("0"); else if(!k) { for(i=1;i<=n;i++) if(dfs(m,i)!=i) break; //printf("%d*\n",i); if(i>n) puts("1"); else puts("0"); } else { for(ans=1,i=1;i<k;i++) ans=ans*s[n]%mod; printf("%I64d\n",ans); } } return 0; }菜鸟成长记