hdu 6038 function 思路 找环+组合数

来源:互联网 发布:数据库中游标的用法 编辑:程序博客网 时间:2024/05/21 14:07

大致题意:给你两个数组a, b, 求满足映射f(i)=bf(ai) 的数量。答案取模。
思路:对于f[i]的i只能在b数组的大小之内, 所以每一次若令f(i)=x时, x一定会出现在a数组的循环节中(可自身循环),可以得到循环节内数的值。
所以只要求出a中的循环节的数量, 找到循环节和映射关系的数量关系,根据组合数的加法和乘法,可得解。

#include<cstdio>#include<stack>#include<queue>#include<algorithm>#include <iostream>#include <string.h>#include <ctype.h>using namespace std;typedef long long LL;const int MAXN=100005;const int mod=1e9+7;int a[MAXN], b[MAXN];int sa[MAXN], sb[MAXN];int main(){    int n, m;    int Case=1;    while(~scanf("%d %d", &n, &m))    {        for(int i=0; i<n; ++i)            scanf("%d", &a[i]);        for(int i=0; i<m; ++i)            scanf("%d", &b[i]);        memset(sa, 0, sizeof(sa));        memset(sb, 0, sizeof(sb));        int tot=0, t=0, k, cnt=0;        for(int i=0; i<n; ++i)        {            t=i;            tot=0;            while(a[t]!=-1)            {                k=a[t];                tot++;                a[t]=-1;                t=k;            }            if(tot)            sa[cnt++]=tot;        }        int cntt=0;        for(int i=0; i<m; ++i)        {            t=i;            tot=0;            while(b[t]!=-1)            {                k=b[t];                tot++;                b[t]=-1;                t=k;            }            if(tot)                sb[cntt++]=tot;        }        LL sum=1;        for(int i=0;i<cnt;++i)        {            LL ans=0;            for(int j=0;j<cntt;++j)            {                if(sa[i]%sb[j]==0)                {                     ans=(ans+sb[j])%mod;                }            }            sum=(sum*ans)%mod;        }        printf("Case #%d: %lld\n", Case++, sum%mod);    }    return 0;}
原创粉丝点击