Function (HDU 6038)

来源:互联网 发布:电子签章软件下载 编辑:程序博客网 时间:2024/06/10 07:26

Function

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


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 from 0 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 #xy" 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

//题意:题目自己先看一边,不好解释,我讲组样例:

3 2
1 0 2
0 1

第一行的3表示a数组有3个元素,2表示b数组有2个元素,接下来两行分别是a、b数组。
根据题意可列方程:
F(0)=b(F(1))
F(1)=b(F(0))
F(2)=b(F(2))

打表:
F(0)       F(1)       F(2)
0            0            0
0            0            1
1            1            0
1            1            1

共有这么4种情况,输出4 。

这么讲应该懂了吧QAQ

//思路

F(0)=b(F(1))
F(1)=b(F(0))
F(2)=b(F(2))

从这里应该可以看出F(0)的值与F(1)是有关的,F(2)的值与它自己有关的,我们可以根据这个建个图:
0->1,1->0,2->2(a图)

还可以看出,b的值与它的下标也有关系,根据这个也再建个图:
0->0,1->1(b图)

我们分别计算出a、b里环的个数和每个环里元素的个数,设b中一个环是X,a中一个环是Y,若X里的元素个数等于Y或是Y的因子(即能被整除),那么a里这个环的情况数+=X的元素个数(因为Y中的一个顶点都可以是X里元素的一种,Y里知道一个顶点的值能推出Y里其他点的值)。那么总数sum=a里每个环的情况数的乘积。

这里算a里环的情况数的时候采用枚举,a里环一个个枚举,每个环去算的时候把b里的环都枚举判断一遍,非常暴力,竟然没TLE,神奇...


#include <iostream>#include <cstdio>#include <cstring>#include <string>#include <cmath>#include <queue>#include <algorithm>using namespace std;const int MAX = 100000 + 100;const int mod = 1000000007;long long sum;int n, m;int a[MAX], b[MAX];int vis[MAX];//图里的点是否被访问过int amap[MAX];//a图int ans;//a图里环的个数int lena[MAX];//a里每个环里的点的个数int bmap[MAX];//b图int cnt;//b图里环的个数int lenb[MAX];//b里每个环里的点的个数//计算图里环的个数和每个环里点的个数//标准的可以去看下tarjan算法,我这个是自己瞎写的,复杂度比较高...int cul(int *map, int *len, int nn){int i, num;int lenth = 1;queue<int>q;memset(vis, 0, sizeof(vis));num = 0;q.push(0);vis[0] = 1;while (true){while (!q.empty()){int now = q.front();q.pop();int next = map[now];if (!vis[next]){vis[next] = 1;q.push(next);lenth++;}}len[num] = lenth;num++;for (i = 0; i < nn; i++){if (vis[i] == 0){q.push(i);vis[i] = 1;lenth = 1;break;}}if (i == nn)break;}return num;}int main(){int Case = 1;while (scanf("%d%d", &n, &m) != EOF){memset(amap, 0, sizeof(amap));memset(bmap, 0, sizeof(bmap));//输入并建a图for (int i = 0; i < n; i++){scanf("%d", &a[i]);amap[i] = a[i];}//输入并建b图for (int i = 0; i < m; i++){scanf("%d", &b[i]);bmap[i] = b[i];}printf("Case #%d: ", Case++);//分别计算a、b图里环的个数和每个环里点的个数ans = cul(amap, lena, n);cnt = cul(bmap, lenb, m);sum = 1;long long kk;for (int i = 0; i < ans; i++){kk = 0;//计算每个环可能的情况数for (int j = 0; j < cnt; j++){if (lena[i] % lenb[j] == 0){kk = (kk+ lenb[j]) % mod;}}//计算总情况数sum *= kk;sum = sum%mod;}sum = sum % mod;printf("%lld\n", sum);}return 0;}