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;}
- HDU 6038 Function
- HDU-6038 Function
- hdu 6038 Function(思维)
- HDU 6038 Function
- hdu 6038 Function
- HDU 6038 Function
- hdu 6038 Function
- HDU 6038 Function
- Function (HDU 6038)
- HDU 6038 Function【思维】
- hdu--6038--Function
- HDU 6038-Function
- hdu 6038 Function
- hdu 6038 Function
- Function HDU-6038
- HDU-6038 Function(思维)
- HDU 6038 Function (数学)
- HDU 6038 Function 置换群
- Ubuntu编译内核驱动模块
- Unity3D NGUI的使用
- MySql删除外键语法 测试思路
- 重入锁
- C++学习之库函数<algorithgm>(1)
- HDU 6038-Function
- [SDOI2009]HH去散步
- javaBean与Map相互转换工具
- ATM取款Final
- C++中的初始化
- C++温故笔记(三)
- Spring的七个事务传播行为
- DOM4J学习笔记 --- Java遍历解析XML
- How Many Equations Can You Find(DFS)