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的主要内容,如果未能解决你的问题,请参考以下文章

HDU 6034 6038

hdu 6038

HDU 6038 Function(思维+寻找循环节)

2017多校第一套&&hdu6038 思维 数学

LeetCode 6038. 向表达式添加括号后的最小结果

(STAT2008/STAT4038/STAT6014/STAT6038)