HDU 6038-Function

来源:互联网 发布:双十一淘宝客服回复 编辑:程序博客网 时间:2024/05/21 19:33

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

Function

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

Problem Description
You are given a permutation a from 0 to n−1 and a permutation b from 0 to m−1.

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
10^9+7.

Input
The input contains multiple test cases.

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.

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 2
1 0 2
0 1
3 4
2 0 1
0 2 3 1

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

分析

题意:给定一个关系式 f(i)=b[f(a[i])] 和数组a,b,计算满足这个关系式不同的可能性数目
可以转化为求环的问题,有多少种方式可以构成题目要求的环,即b的环可以有多少种方式画成a的环
样例一:

i: 0,1,2
a: 1,0,2
b: 0,1

根据关系式 f(i)=b[f(a[i])] 可得

///a环
f(0)=b[f(a[0])]=b[f(1)]
f(1)=b[f(a[1])]=b[f(0)]

f(2)=b[f(a[2])]=b[f(2)]
///易看出a[0]和a[1]组成一个环,a[2]单独成环

///b环
如果f(0)=b[0]
因为f(0)=b[f(1)],则f(1)=0=b[0]
因为f(1)=b[f(0)],则f(0)=0=b[0]

如果f(0)=b[1]
因为f(0)=b[f(1)],则f(1)=1=b[1]
因为f(1)=b[f(0)],则f(0)=1=b[1]
///易看出b[0]单独成环,b[1]单独成环

这里写图片描述

由图易知,a的两个环都可以由b的两个环构成,则由b构成a总共有2+2=4种方式。
样例二:

i: 0,1,2,3
a: 2,0,1
b: 0,2,3,1

根据关系式 f(i)=b[f(a[i])] 可得

///a环
f(0)=b[f(a[0])]=b[f(2)]
f(1)=b[f(a[1])]=b[f(0)]
f(2)=b[f(a[2])]=b[f(1)]
///易看出a[0],a[1],a[2]组成一个环

///b环
如果f(0)=b[0]
因为f(0)=b[f(2)],则f(2)=0=b[0]
因为f(2)=b[f(1)],则f(1)=0=b[0]
因为f(1)=b[f(0)],则f(0)=0=b[0]

如果f(0)=b[1]
因为f(0)=b[f(2)],则f(2)=1=b[3]
因为f(2)=b[f(1)],则f(1)=3=b[2]
因为f(1)=b[f(0)],则f(0)=2=b[1]
///易看出b[0]单独成环,b[1],b[2],b[3]组成一个环

这里写图片描述

由图易知,a的一个环可以由b的两个环构成,但b的第二个环与a环可以有三种不同的对应关系,则由b构成a总共有1+3=4种方式。

所以也就是b环长度应为a环长度的因数才能满足与a环的对应关系,只要这个思路明白了,代码很好理解,记得不断对1e9+7取余

#include <bits/stdc++.h>using namespace std;#define ll long longconst int MOD=1e9+7;const int maxn=100100;int n,m,cal[2][maxn],a[maxn],b[maxn],ans=1;///cal[0][i]表示b环中长度为i的环出现的次数///cal[1][i]表示a环中长度为i的环出现的次数bool vis[maxn];///vis[i]表示位置i是否出现过,出现过则说明成环void dfs(int t, int l, int *a, int k){    if(vis[t])    {        cal[k][l]++;        return;    }    vis[t] = 1;    dfs(a[t],l+1,a,k);}int main(){    int ca = 0;    while(~scanf("%d%d",&n,&m))    {        for(int i=0; i<n; i++)            scanf("%d",a+i);        for(int i=0; i<m; i++)            scanf("%d",b+i);        memset(cal,0,sizeof(cal));        memset(vis,0,sizeof(vis));        for(int i=0; i<m; i++)            if(!vis[i])dfs(i,0,b,0);        memset(vis,0,sizeof(vis));        for(int i=0; i<n; i++)            if(!vis[i])dfs(i,0,a,1);        ans=1;        for(int i=1; i<=n; i++)            if(cal[1][i])            {                int lim=(int)sqrt(i+0.5),ta = 0;                for(int j=1; j<=lim; j++)                    if(i%j==0)                    {                        (ta+=(ll)cal[0][j]%MOD*j%MOD)%=MOD;                        if(j*j!=i)ta+=((ll)cal[0][i/j]%MOD*(i/j)%MOD)%MOD;                    }                for(int j=1; j<=cal[1][i]; j++)                    ans=(ll)ans*ta%MOD;            }        printf("Case #%d: %d\n",++ca,ans);    }    return 0;}