hdu 6038
Posted 早知如此绊人心,何如当初莫相识。
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu 6038相关的知识,希望对你有一定的参考价值。
题意:给出a,b序列,求多少种f序列,f序列是f(i)=b(f(ai)).
思路:从例子出发3 4
2 0 1
0 2 3 1
可以知道a序列有个长度为3的循环节,即a[0]=2,a[1]=0,a[2]=1, b序列有长度为1和3的循环节 长度为1的:a[0]=0;
长度为3的:a[1]=2,a[2]=3,a[3]=1;
那么a长度3的循环节自然可以匹配长度为1的和长度为3的循环节,但如果我b改为0 2 1 3,它的循环节就变成长度为1和2的,那么就只能匹配长度为1的循环节,可以自己手动模拟下,
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int N=1e5+10; 5 const ll mod=1e9+7; 6 7 int a[N],b[N]; 8 int aa[N],bb[N]; 9 int vis[N]; 10 11 int main(){ 12 int k=1; 13 int n,m; 14 while(scanf("%d%d",&n,&m)!=EOF){ 15 for(int i=0;i<n;i++) scanf("%d",&a[i]); 16 for(int i=0;i<m;i++) scanf("%d",&b[i]); 17 memset(vis,0,sizeof(vis)); 18 memset(aa,0,sizeof(aa)); 19 memset(bb,0,sizeof(bb)); 20 for(int i=0;i<n;i++){ 21 int cnt=0; 22 int x=i; 23 while(!vis[x]){ 24 cnt++; 25 vis[x]=1; 26 x=a[x]; 27 } 28 //cout<<cnt<<endl; 29 aa[cnt]++;//a该循环节的个数++ 30 } 31 memset(vis,0,sizeof(vis)); 32 for(int i=0;i<m;i++){ 33 int cnt=0; 34 int x=i; 35 while(!vis[x]){ 36 cnt++; 37 vis[x]=1; 38 x=b[x]; 39 } 40 //cout<<cnt<<endl; 41 bb[cnt]++;//b该循环节的个数++ 42 } 43 ll sum=1; 44 for(int i=1;i<=n;i++){ 45 if(aa[i]){ 46 // cout<<i<<endl; 47 ll ans=0; 48 for(int j=1;j*j<=i;j++){//在b的循环节中找到和a匹配的,即a的因子 49 if(i%j==0){ 50 ans=(ans+bb[j]*j)%mod;//循环节的个数*循环节的长度,代表循环节里的这些数都可以形成f 51 // cout<<bb[j]<<" "; 52 if(j*j!=i){ 53 ans=(ans+bb[i/j]*(i/j))%mod; 54 } 55 } 56 } 57 // cout<<ans<<endl; 58 while(aa[i]--){//对于a每个循环节都有ans个,所以* 59 sum=sum*(ans)%mod; 60 } 61 } 62 } 63 printf("Case #%d: ",k++); 64 printf("%I64d\n",sum); 65 } 66 return 0; 67 }
以上是关于hdu 6038的主要内容,如果未能解决你的问题,请参考以下文章