2017 多校 Function(置换群

来源:互联网 发布:网络桥接怎么设置 编辑:程序博客网 时间:2024/06/06 05:46

传送门

Function

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


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

Recommend
liuyiding   |   We have carefully selected several similar problems for you:  6044 6043 6042 6041 6040 
 

题目大意:

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

现在定义F(i)=bF(ai);

问有多少种取值,使得F(i)全部合法。


写出样例2的公式:


①F(0)=bF(2)

②F(1)=bF(0)

③F(2)=bF(1)


设想一下,这个题仔细想想有映射的关系,如果定F(i)中的i一定会有对应的b 也就是说确定一个值可以确定整个值。

多往b里推几下,会发现最终会有F(i)=bbbbbbb(i) 这样递归可以得到最终的循环节 也就是一个环。

预处理A,得到A 循环节个数和 形成的循环节。同样预处理B。

如果在A循环节的基础上,B里的一定是A循环节的因子才能完成A这个循环。

对于A数组中长度为D的一个环,如果B数组中有一个环的长度为d,并且如果D%d==0.那么这个B数组的这个环的所有值,都可以作为A数组中这个环的值。那么对于A数组中的这个环来讲,答案数就多了d个。

最终的答案就是每个循环节累乘的结果

//china no.1//#pragma comment(linker, "/STACK:1024000000,1024000000")#include <vector>#include <iostream>#include <string>#include <map>#include <stack>#include <cstring>#include <queue>#include <list>#include <stdio.h>#include <set>#include <algorithm>#include <cstdlib>#include <cmath>#include <iomanip>#include <cctype>#include <sstream>#include <functional>#include <stdlib.h>#include <time.h>#include <bitset>using namespace std;#define pi acos(-1)#define endl '\n'#define srand() srand(time(0));#define me(x,y) memset(x,y,sizeof(x));#define foreach(it,a) for(__typeof((a).begin()) it=(a).begin();it!=(a).end();it++)#define close() ios::sync_with_stdio(0); cin.tie(0);typedef long long LL;const int INF=0x3f3f3f3f;const LL LINF=0x3f3f3f3f3f3f3f3fLL;const int dx[]={-1,0,1,0,1,-1,-1,1};const int dy[]={0,1,0,-1,-1,1,-1,1};const int maxn=1e3+1e2;const int maxx=1e5+1e2;const double EPS=1e-7;const LL MOD=1e9+7;#define mod(x) ((x)%MOD);template<class T>inline T min(T a,T b,T c) { return min(min(a,b),c);}template<class T>inline T max(T a,T b,T c) { return max(max(a,b),c);}template<class T>inline T min(T a,T b,T c,T d) { return min(min(a,b),min(c,d));}template<class T>inline T max(T a,T b,T c,T d) { return max(max(a,b),max(c,d));}#define FOR(x,n,i) for(int i=x;i<=n;i++)#define FOr(x,n,i) for(int i=x;i<n;i++)#define W while#define sgn(x) ((x) < 0 ? -1 : (x) > 0)#define bug printf("***********\n");vector<int>G[maxx];stack<int>S;map<int,LL>mp;int vis[maxx],dfn[maxx],low[maxx],bel[maxx],num[maxx],res,a[maxx],b[maxx],num1[maxx];int cont=1,n,m;LL ans[maxx];void dfs(int x){    dfn[x]=low[x]=cont++;    S.push(x);vis[x]=1;    int len=G[x].size();    for(int i=0; i<len; i++)        if(!vis[G[x][i]])        {            dfs(G[x][i]);            low[x]=min(low[x],low[G[x][i]]);        }        else if(vis[G[x][i]]==1)            low[x]=min(low[x],dfn[G[x][i]]);    if(dfn[x]==low[x])    {        res++;        while(1)        {            int t=S.top();            S.pop();            vis[t]=2;  //访问完成            bel[t]=res;            if(x==t)break;        }    }}void init(){    me(dfn,0);me(vis,0);me(low,0);me(bel,0);me(a,0);me(b,0);    me(num1,0);mp.clear();me(num,0);me(ans,0);    res=0;cont=1;}void INIT(){    me(dfn,0);me(vis,0);me(low,0);me(bel,0);me(num,0);    res=0;cont=1;}inline int Scan(){    int Res=0,ch,Flag=0;    if((ch=getchar())=='-')Flag=1;    else if(ch>='0' && ch<='9')Res=ch-'0';    while((ch=getchar())>='0'&&ch<='9')Res=Res*10+ch-'0';    return Flag ? -Res : Res;}int cas=1;int main(){    //freopen("1006.in", "r", stdin);    while(scanf("%d%d",&n,&m)!=EOF)    {        init();        for(int i=1;i<=n;i++)        {            scanf("%d",&a[i]);            a[i]++;            G[a[i]].push_back(i);        }        for(int i=1;i<=m;i++)        {            scanf("%d",&b[i]);            b[i]++;        }        for(int i=1;i<=n;i++)            if(!vis[i]) dfs(i);        for(int i=1;i<=n;i++)            num1[bel[i]]++;        int val=res;        for(int i=1;i<=n;i++)            G[i].clear();        INIT();        for(int i=1;i<=m;i++)            G[b[i]].push_back(i);        for(int i=1;i<=m;i++)            if(!vis[i]) dfs(i);        for(int i=1;i<=m;i++)            num[bel[i]]++;        for(int i=1;i<=m;i++)            mp[num[i]]+=num[i];        for(int i=1;i<=m;i++)            G[i].clear();        for(int i=1;i<=val;i++)            for(int j=1;j<=sqrt(num1[i]);j++)        {            if(num1[i]%j==0)            {                ans[i]+=mp[j];                if(num1[i]/j!=j)                    ans[i]+=mp[num1[i]/j];            }        }        LL out;        for(int i=1;i<=val;i++)        {            if(i==1) out=ans[i]%MOD;            else            {                out*=ans[i];                out%=MOD;            }        }        printf("Case #%d: %I64d\n",cas++,out);    }}