HDU 6038 Function —— 2017 Multi-University Training 1

Function

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)

Total Submission(s): 1610    Accepted Submission(s): 755

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 1e9+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 n1e6, m1e6.
 
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 2 1 0 2 0 1 3 4 2 0 1 0 2 3 1
 
Sample Output
Case #1: 4 Case #2: 4
 
 
题目大意:给你数列a,b,然后它们之间有函数关系f(i)=bf(ai) ,求满足要求的映射关系的个数。
思路:如果把f(ai)按照上述函数扩展下去,发现它是循环的,并且a的循环一定是b的循环的整倍数, 那么就可以跑dfs求出a和b的循环节(以及相等循环节的个数),最后求和即可。
 
AC代码:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath> 
using namespace std;
const int MOD=1e9+7;
const int MAXN=100010;
int a[MAXN],b[MAXN];
int la[MAXN],lb[MAXN];
bool vis[MAXN];
void dfsa(int t, int l, int *num){
    if(vis[t]){
        la[l]++;
        return;
    }
    vis[t]=1;
    dfsa(num[t], l+1, num);
}
void dfsb(int t, int l, int *num){
    if(vis[t]){
        lb[l]++;
        return;
    }
    vis[t]=1;
    dfsb(num[t], l+1, num);
}
int main()
{
    int n,m,t=0;
    while(~scanf("%d%d", &n, &m))
    {
        for(int i=0;i<n;i++)
            scanf("%d", a+i);
        for(int j=0;j<m;j++)
            scanf("%d", b+j);
        memset(la, 0, sizeof(la));
        memset(lb, 0, sizeof(lb));
        
        memset(vis, 0, sizeof(vis));
        for(int i=0;i<n;i++)
            if(!vis[i])
                dfsa(i, 0, a);
                
        memset(vis, 0, sizeof(vis));
        for(int i=0;i<m;i++)
            if(!vis[i])
                dfsb(i, 0, b);
        
        int res=1;
        for(int i=1;i<=n;i++){
            if(la[i]){
                int k=(int)(sqrt(i*1.0)+0.5),tmp=0;
                for(int j=1;j<=k;j++){
                    if(i%j==0){
                        tmp=(tmp+lb[j]*j%MOD)%MOD;
                        if(j*j!=i)
                            tmp=(tmp+lb[i/j]*(i/j)%MOD)%MOD;
                    }
                }
                for(int j=0;j<la[i];j++)
                    res=res*tmp%MOD;
            }
        }
        printf("Case #%d: %d
", ++t, res);
    }
 return 0;  
}

  嗯,是个图论题。

原文地址:https://www.cnblogs.com/MasterSpark/p/7265841.html