Function
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 1502 Accepted Submission(s): 707
Define that the domain of function f is the set of integers from 0 to n−1 , and the range of it is the set of integers from 0 to m−1 .
Please calculate the quantity of different functions f satisfying that f(i)=bf(ai) for each i from 0 to n−1 .
Two functions are different if and only if there exists at least one integer from 0 to n−1 mapped into different integers in these two functions.
The answer may be too large, so please output it in modulo 109+7 .
For each case:
The first line contains two numbers n, m . (1≤n≤100000,1≤m≤100000)
The second line contains n numbers, ranged from 0 to n−1 , the i -th number of which represents ai−1 .
The third line contains m numbers, ranged from 0 to m−1 , the i -th number of which represents bi−1 .
It is guaranteed that ∑n≤106, ∑m≤106 .
3 2 1 0 2 0 1 3 4 2 0 1 0 2 3 1
Case #1: 4 Case #2: 4
那么 f(i) 的值在置换 b 中所在的循环节的长度必须为 l 的因数。
而如果 f(i) 的值确定下来了,这个循环节的另外 l−1 个数的函数值也都确定下来了。
答案就是 ∑i=1k∑j∣lij⋅calj 改为 ∏i=1k∑j∣lij⋅calj ,其中 k 是置换 a 中循环节的个数, li 表示置换 a 中第 i 个循环节的长度, calj 表示置换 b 中长度为 j 的循环节的个数。
时间复杂度是 O(n+m) 。
我的思路: 分析样例:3 4
2 0 1
0 2 3 1
可以推出:a序列有个长度为3的循环节,即a[0]=2,a[1]=0,a[2]=1。
b序列有长度为1和3的循环节 长度为1的:b[0]=0;长度为3的:b[1]=2,b[2]=3,b[3]=1;
求解:
1,要满足f(i)=b[f(a[i])];枚举数列a中的循环x,然后同理再找出b中循环y,但需要满足y的长度是x的因子
2,由于循环可以旋转,则每一个长度为len(y)的循环y贡献的方法个数为tol(y)=num(y)*len(y) (分别表
示y循环的长度和个数),将该x的每一个tol(y)进行累加,tol(x)=tol(y1)+tol(y2)+....+tol(yn);yi都是
x的因子。
3,由于不同x之间相互独立,ans=tol(x1)*tol(x2)*.....*tol(xn);
代码:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
#include<bits/stdc++.h>
using namespace std; typedef long long ll; const int N=1e5+ 10; const ll mod=1e9+ 7; int a[N],b[N]; int aa[N],bb[N]; int vis[N]; int main() { int k= 1; int n,m; while(scanf( "%d%d",&n,&m)!=EOF) { for( int i= 0; i<n; i++) scanf( "%d",&a[i]); for( int i= 0; i<m; i++) scanf( "%d",&b[i]); memset(vis, 0, sizeof(vis)); memset(aa, 0, sizeof(aa)); memset(bb, 0, sizeof(bb)); for( int i= 0; i<n; i++) { int cnt= 0; int x=i; while(!vis[x]) { cnt++; vis[x]= 1; x=a[x]; } aa[cnt]++; ///a该循环节的个数++ } memset(vis, 0, sizeof(vis)); for( int i= 0; i<m; i++) { int cnt= 0; int x=i; while(!vis[x]) { cnt++; vis[x]= 1; x=b[x]; } bb[cnt]++; ///b该循环节的个数++ } ll sum= 1; for( int i= 1; i<=n; i++) { if(aa[i]) { ll ans= 0; for( int j= 1; j<=i; j++) ///在b的循环节中找到和a匹配的,即a的因子 if(i%j== 0) ans=(ans+bb[j]*j)%mod; ///循环节的个数*循环节的长度,代表循环节里的这些数都可以形成f while(aa[i]--) ///对于a每个循环节都有ans个,所以* sum=sum*(ans)%mod; } } printf( "Case #%d: ",k++); printf( "%I64d\n",sum); } return 0; } |