2017 Multi-University Training Contest

来源:互联网 发布:周扬青淘宝店铺货源 编辑:程序博客网 时间:2024/06/07 10:09

Function

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


Problem Description
You are given a permutationa 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
 

题目大意:

给你一个数组A,和一个数组B,数组A是【0~n-1】的排咧,数组B是【0~m-1】的排列。

现在定义F(i)=bF(ai);问有多少种取值,使得F(i)全部合法


分析:这个主要是找循环节
比如说:如果 a 序列是 2 0 1 那么我们可以发现
             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)]

那么f(0) f(1) f(2) 也是循环的

如果想找出这样的函数,必须值域里也存在同样长度的循环节或者存在其约数长度的循环节
那么就是找两个序列的循环节,对于定义域里面的每一个循环节都找出来有多少种和他对应的,

最后乘起来就是答案了


#include<cstdio>#include<map>#include<cstring>#define mo 1000000007using namespace std;typedef long long ll;const int maxn = 1e5 + 5;ll a[maxn];ll b[maxn];ll num1[maxn], num2[maxn];int main(){    int n, m, kase = 0;    while (~scanf("%d%d", &n, &m))    {        memset(num2, 0, sizeof(num2));        int totfa = 0;        for (int i = 0; i < n; i++)        {            scanf("%lld", &a[i]);        }        for (int i = 0; i < n; i++)        {            ll tot = 0;            int k = i;            while (a[k] != -1)            {                tot++;                int t = k;                k = a[k];                a[t] = -1;            }            if (tot)            {                num1[++totfa] = tot;            }        }        for (int j = 0; j < m; j++)        {            scanf("%lld", &b[j]);        }        for (int i = 0; i < m; i++)        {            ll tot = 0;            int k = i;            while (b[k] != -1)            {                tot++;                int t = k;                k = b[k];                b[t] = -1;            }            if (tot)            {                num2[tot]++;            }        }        ll ans = 1;        for (int i = 1; i <= totfa; i++)        {            ll ansl = 0;            for (int j = 1; j * j <= num1[i]; j++)            {                if (num1[i] % j == 0)                {                    if (j * j == num1[i])                    {                        ansl += num2[j] * j;                    }                    else                    {                        ansl += num2[j] * j + num2[num1[i] / j] * num1[i] / j;                    }                }            }            ans = (ans * ansl) % mo;        }        printf("Case #%d: %lld\n", ++kase, ans);    }}



原创粉丝点击