hdu 6038 Function

来源:互联网 发布:淘宝篮球鞋店推荐 编辑:程序博客网 时间:2024/06/06 11:43

转自:http://blog.csdn.net/cysjiang/article/details/76090902

题意:
给你一个a序列,代表0到n-1的排列;一个b序列代表0到m-1的排列。问你可以找出多少种函数关系,满足f(i)=b[f(a[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 <bits/stdc++.h>using namespace std;const int N = 1e6+100;int a[N],b[N],num1[N],num2[N];typedef long long ll;const int mod = 1e9+7;int main(){    int n,m;            int cas=1;    while(scanf("%d%d",&n,&m)!=EOF)    {        memset(num2,0,sizeof(num2));        for(int i=0;i<n;i++)            scanf("%d",&a[i]);        for(int i=0;i<m;i++)            scanf("%d",&b[i]);        int totfa=0;        for(int i=0;i<n;i++)        {            int k=i;            int tot=0;            while(a[k]!=-1)            {                int t=k;                k=a[k];                a[t]=-1;                tot++;            }            if(tot)num1[totfa++]=tot;        }        for(int i=0;i<m;i++)        {            int k=i;            int tot=0;            while(b[k]!=-1){                int t=k;                k=b[k];                b[t]=-1;                tot++;            }            if(tot)num2[tot]++;        }        long long total=1;        for(int i=0;i<totfa;i++)        {        ll tol=0;        for(int j=1;j*j<=num1[i];j++)        {            if(j*j==num1[i])            {                tol=(tol+num2[j]*j)%mod;            }            else if(num1[i]%j==0){                tol=(tol+num2[j]*j%mod+num2[num1[i]/j]*(num1[i]/j)%mod)%mod;            }        }        total*=tol;        total%=mod;        }        printf("Case #%d: %lld\n",cas++,total);    }}
原创粉丝点击