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

时间:2022-04-23 20:27:56

http://acm.hdu.edu.cn/showproblem.php?pid=6038

题意:
给出两个序列,一个是0~n-1的排列a,另一个是0~m-1的排列b,现在求满足HDU 6038 Function(思维+寻找循环节)的f的个数。

 

思路:

先看一下样例吧:

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

对于这组数来说,假如我们先指定了f(0)对应的在b中的值,那么根据第2个式子,就可以得出f(1),根据f(1)就又可以得出f(2),最后根据f(2)就可以检验f(0)的值是否正确。

这也就是说,对于a中的一个循环节,只要确定了其中一个数所映射的值,那么其它数就都被相应的确定了。


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

所以我们需要先计算出a和b中的循环节个数和每个循环节对应的个数,然后根据循环节的因子关系就可以判断是否成立。

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<cstdio>
 5 #include<sstream>
 6 #include<vector>
 7 #include<stack>
 8 #include<queue>
 9 #include<cmath>
10 #include<map>
11 #include<set>
12 using namespace std;
13 typedef long long ll;
14 typedef pair<int,int> pll;
15 const int INF = 0x3f3f3f3f;
16 const int maxn = 1e5 + 5;
17 const int mod = 1e9+7;
18 
19 int n, m;
20 
21 int a[maxn], b[maxn];
22 int vis[maxn];
23 
24 vector<int> A;
25 vector<int> B;
26 
27 int main()
28 {
29     //freopen("in.txt","r",stdin);
30     int kase=0;
31     while(~scanf("%d%d",&n,&m))
32     {
33         for(int i=0;i<n;i++)  scanf("%d",&a[i]);
34         for(int i=0;i<m;i++)  scanf("%d",&b[i]);
35 
36         A.clear();
37         memset(vis,0,sizeof(vis));
38         for(int i=0;i<n;i++)
39         {
40             int cur=i,cnt=1;
41             if(!vis[i])
42             {
43                 vis[i]=1;
44                 while(a[cur]!=i)
45                 {
46                     cur=a[cur];
47                     vis[cur]=1;
48                     cnt++;
49                 }
50                 A.push_back(cnt);
51             }
52         }
53 
54         B.clear();
55         memset(vis,0,sizeof(vis));
56         for(int i=0;i<m;i++)
57         {
58             int cur=i, cnt=1;
59             if(!vis[i])
60             {
61                 vis[i]=1;
62                 while(b[cur]!=i)
63                 {
64                     cur=b[cur];
65                     vis[cur]=1;
66                     cnt++;
67                 }
68                 B.push_back(cnt);
69             }
70         }
71 
72         ll ans=1;
73         for(int i=0;i<A.size();i++)
74         {
75             ll tmp=0;
76             for(int j=0;j<B.size();j++)
77             {
78                 if(A[i]%B[j]==0)  tmp=(tmp+B[j])%mod;
79             }
80             ans=ans*tmp%mod;
81         }
82         printf("Case #%d: %d\n",++kase,ans);
83     }
84     return 0;
85 }