6038 Function

来源:互联网 发布:linux java环境变量 编辑:程序博客网 时间:2024/06/16 06:09

Function

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


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 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
 

Source

2017 Multi-University Training Contest - Team 1 



思路:

函数的映射。每个f(x)与ax关联关系链成环。必须有相应的b与a对应(一个a只能有一个b,一个b可以有多个a对应)。

先处理a和b有几个环  ,再 b组成(每个)a环的种类数。  一个有k个元素的b环有k种可能有num[k]=x个有k个元素的b 环就是有 num[k]*k种可能。a环元素有k个元素同时可以由k的因子成环(如果k为4 ,k可以由4个元素的、2个元素的、1个元素的环组成)所以对于一个a环可以由sum=num[x1]*x1+num[x2]*x2+num[x3]*x3…. (x1,x2,x3为k的因子)。  如果有t个有k个因子的a环 ans*=sum1^t1;所有a环答案相乘就是最后的答案。

AC:

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <cmath>typedef long long LL;using namespace std;int vis[100100]={0};int mem[100100]={0},VIS[100100]={0};int cira[100100]={0},cirb[100100]={0};int main(){    int n,m;    int v=1;    while(scanf("%d%d",&n,&m)!=EOF)    {        int a[100100]={0},b[100100]={0};        for(int i=0;i<n;i++)scanf("%d",&a[i]);        int s,next,num=1;        memset(VIS,0,sizeof(VIS));        memset(cira,0,sizeof(cira));        memset(cirb,0,sizeof(cirb));        memset(vis,0,sizeof(vis));        memset(mem,0,sizeof(mem));        ///the circle of A        int d=0;        for(int i=0;i<n;i++)        {            s=i,next=a[i],num=1;            if(VIS[s]==1)continue;            VIS[s]=1;            //printf("s= %d \n",s);            while(next!= s)            {                VIS[next]=1;                next=a[next];                num++;            }            cira[num]++;            if(!vis[num])mem[d++]=num;            vis[num]=1;        }        //for(int i=0;i<10;i++)printf("ciara[%d]=%d ",i,cira[i]);        for(int i=0;i<m;i++)scanf("%d",&b[i]);        memset(VIS,0,sizeof(VIS));        ///the circle of B        for(int i=0;i<m;i++)        {            s=i,next=b[i],num=1;            if(VIS[s]==1)continue;            VIS[s]=1;            //printf("s= %d \n",s);            while(next!= s)            {                VIS[next]=1;                next=b[next];                num++;            }            cirb[num]++;        }        //for(int i=0;i<10;i++)printf("ciarb[%d]=%d ",i,cirb[i]);        LL ans=1;        //cout<<"a:";        for(int i=0;i<d;i++)        {            int k=mem[i];            //printf("%d \n",k);            LL temp=0;            for(int j=1;j<=k;j++)            {                if(k%j==0)temp+=j*cirb[j];            }            //cout<<"temp:"<<temp<<endl;            LL T=1;            for(int j=1;j<=cira[k];j++)                T*=temp;            ans*=T;        }        //cout<<endl;        printf("Case #%d: %lld\n",v++,ans);    }}