hdu 6038 Function

来源:互联网 发布:addiction动作数据mmd 编辑:程序博客网 时间:2024/06/14 09:55

Function

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 1621    Accepted Submission(s): 758


Problem Description
You are given a permutation a from 0 to n1 and a permutation b from 0 to m1.

Define that the domain of function f is the set of integers from 0 to n1, and the range of it is the set of integers from 0 to m1.

Please calculate the quantity of different functions f satisfying that f(i)=bf(ai) for each i from 0 to n1.

Two functions are different if and only if there exists at least one integer from0 to n1 mapped into different integers in these two functions.

The answer may be too large, so please output it in modulo 109+7.
 

Input
The input contains multiple test cases.

For each case:

The first line contains two numbers n,m.(1n100000,1m100000)

The second line contains n numbers, ranged from 0 to n1, the i-th number of which represents ai1.

The third line contains m numbers, ranged from 0 to m1, the i-th number of which represents bi1.

It is guaranteed that n106,m106.
 

Output
For each test case, output "Case #x:y" in one line (without quotes), where x indicates the case number starting from 1 and y denotes the answer of corresponding case.
 

Sample Input
3 21 0 20 13 42 0 10 2 3 1
 

Sample Output
Case #1: 4Case #2: 4
 

Source
2017 Multi-University Training Contest - Team 1


因为a,b都是分别0~n-1,0~m-1内的数,所以a,b内一定存在环

例如
2 0 1
0 2 3 1
f(0)=b(f(2))
f(1)=b(f(0))
f(2)=f(f(1))
因此a中存在2->0->1->2的环

并且b中也存在环
0 1 2 3
0 2 3 1    --> 0->0,1->2->3->1的环

所以这里就有一个结论:
a中的环能映射到b中的条件:b环的长度必须是a环长度的因子

这样对a环枚举每个b环,若长度满足条件,则加上b环长度(==存在的函数数量)
最后乘起来就是答案了
这里还有就是找环的时候可以用类似深搜的思想沿着a数组一直搜下去知道遇到i==a[j]时停止

#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#include<vector>#define MAXN 1000010#define MAXM 100010using namespace std;typedef long long int ll;const int MOD = 1e9+7;ll n,m;ll a[MAXM],b[MAXM];ll vis[MAXM];vector<int> len1,len2;  //记录a,b内每个环的长度以及总共的个数void solve(ll a[],ll s,int flag)  //类似深搜,将一个环的归为一类{memset(vis,0,sizeof(vis));for(int i=0;i<s;i++){if(vis[i]) continue;ll k=a[i];ll slen=1;vis[i]=1;while(k!=i){slen++;vis[k]=1;k=a[k];}if(flag==1)len1.push_back(slen);elselen2.push_back(slen);}}int main(){ll ans;int t=0;while(scanf("%lld%lld",&n,&m)!=EOF){t++;ans=1;len1.clear();len2.clear();for(ll i=0;i<n;i++)scanf("%lld",&a[i]);for(ll i=0;i<m;i++)scanf("%lld",&b[i]);solve(a,n,1);solve(b,m,2);for(int i=0;i<len1.size();i++){ll res=0;for(int j=0;j<len2.size();j++){if(len1[i]%len2[j]==0)   //一个a环对应的B环是加的关系,表示一个a环的节点可以对应b环中这么多的数res=(res+len2[j])%MOD;}ans=(ans*res)%MOD;   //注意每一个a之间是乘的关系即使是a环内有相同的节点数,也要相乘,因为是不同的两个环}printf("Case #%d: %lld\n",t,ans%MOD);}return 0;}