Function
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 327 Accepted Submission(s): 129
Problem Description
You are given a permutation
a
from
0
to
n−1
and a permutation
b
from
0
to
m−1
.
Define that the domain of function f is the set of integers from 0 to n−1 , and the range of it is the set of integers from 0 to m−1 .
Please calculate the quantity of different functions f satisfying that f(i)=bf(ai) for each i from 0 to n−1 .
Two functions are different if and only if there exists at least one integer from 0 to n−1 mapped into different integers in these two functions.
The answer may be too large, so please output it in modulo 109+7 .
Define that the domain of function f is the set of integers from 0 to n−1 , and the range of it is the set of integers from 0 to m−1 .
Please calculate the quantity of different functions f satisfying that f(i)=bf(ai) for each i from 0 to n−1 .
Two functions are different if and only if there exists at least one integer from 0 to n−1 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 . (1≤n≤100000,1≤m≤100000)
The second line contains n numbers, ranged from 0 to n−1 , the i -th number of which represents ai−1 .
The third line contains m numbers, ranged from 0 to m−1 , the i -th number of which represents bi−1 .
It is guaranteed that ∑n≤106, ∑m≤106 .
For each case:
The first line contains two numbers n, m . (1≤n≤100000,1≤m≤100000)
The second line contains n numbers, ranged from 0 to n−1 , the i -th number of which represents ai−1 .
The third line contains m numbers, ranged from 0 to m−1 , the i -th number of which represents bi−1 .
It is guaranteed that ∑n≤106, ∑m≤106 .
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 2 1 0 2 0 1 3 4 2 0 1 0 2 3 1
Sample Output
Case #1: 4 Case #2: 4
Source
题意:给出两个排列,a和b,求满足映射的f[i]=b_f[a[i]]的个数。
其实相当于排列b也是一个映射,把两个映射转化成两个图。
因为是1-n的排列,所以根据映射关系组成的一定是一个一个的环。
为了将f的映射和b的对应起来,对于f中的每个环,当b中的环的长度为f中的环的因数时,则可以匹配。最后再组合一下答案即可。
include <cstring>
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <cmath>
#include <vector>
#include <stack>
using namespace std;
typedef long long ll;
const int max_n=200010;
const ll mod=1e9+7;
vector<int> G[max_n];
int pre[max_n],lowlink[max_n],sccno[max_n],dfs_clock,scc_cnt;
int counter[max_n];
stack<int> S;
void dfs(int u)
{
pre[u]=lowlink[u]=++dfs_clock;
S.push(u);
for(int i=0;i<G[u].size();i++)
{
int v=G[u][i];
if(!pre[v])
{
dfs(v);
lowlink[u]=min(lowlink[u],lowlink[v]);
}
else if(!sccno[v])
{
lowlink[u]=min(lowlink[u],pre[v]);
}
}
if(lowlink[u]==pre[u])
{
scc_cnt++;
while(1)
{
int x=S.top();S.pop();
sccno[x]=scc_cnt;
counter[scc_cnt]++;
if(x==u)
break;
}
}
}
void find_scc(int n)
{
dfs_clock=scc_cnt=0;
while(S.size())
S.pop();
memset(sccno,0,sizeof(sccno));
memset(pre,0,sizeof(pre));
for(int i=0;i<max_n;i++)
counter[i]=0;
for(int i=0;i<n;i++)
{
if(!pre[i])
dfs(i);
}
}
int a[max_n],b[max_n];
ll na[max_n],nb[max_n];
ll quickpow(ll num,ll k){
ll res=1;
while(k){
if(k&1)
res=(res*num)%mod;
num=(num*num)%mod;
k>>=1;
}
return res;
}
int main(){
ll n,m;
ll maxn;
int cas=1;
while(~scanf("%lld%lld",&n,&m)){
memset(na,0,sizeof(na));
memset(nb,0,sizeof(nb));
for(int i=0;i<n;i++)
scanf("%d",a+i);
for(int i=0;i<m;i++)
scanf("%d",b+i);
for(int i=0;i<max_n;i++)
G[i].clear();
for(int i=0;i<n;i++)
G[a[i]].push_back(i);
find_scc(n);
maxn=0;
for(int i=1;i<=scc_cnt;i++){
na[counter[i]]++;
maxn=max(maxn,(ll)counter[i]);
}
for(int i=0;i<max_n;i++)
G[i].clear();
for(int i=0;i<m;i++)
G[i].push_back(b[i]);
find_scc(m);
for(int i=1;i<=scc_cnt;i++)
nb[counter[i]]++;
ll res=1;
int ok=1;
for(ll i=1;i<=maxn;i++){
ll tmp=0;
if(!na[i]) continue;
ll bound=sqrt(i);
int flag=0;
for(ll j=1;j<=bound;j++){
if(i%j) continue;
ll x=i/j;
ll y=i/x;
if(nb[x]!=0||nb[y]!=0)
flag=1;
tmp=(tmp+(x*nb[x])%mod)%mod;
if(y!=x)
tmp=(tmp+(y*nb[y])%mod)%mod;
}
ok=flag;
if(ok==0) break;
res=(res*quickpow(tmp,na[i]))%mod;
//res=(res*((na[i]*tmp)%mod))%mod;
}
printf("Case #%d: %lld\n",cas++,ok==1?res:0);
}
return 0;
}