还是太菜了这么多人过的一道题目,自己却想了这么久,然而到现在还是不是很清楚这个东西,先写一个题解吧,题目给的是一个公式
f(i)=bf(ai)
给定了b数组和a数组,然后问有多少种映射的方案满足上式,
首先来看下样例
f(0)=bf(1)
f(1)=bf(0)
f(2)=bf(2)
很容易看出 如果在a数组上从0开始,每次以a的值跳转,那么就形成上面的循环节。现在a的循环节确定了,在来看b,对于上述式子,其实b也是在循环 ,但是f的值可以重复,所以其实b的循环节可以是a的循环节的因子,然后就是求一个b的循环节放进a的情况数,因为可以是从b的任何一个点开始然后就是把b的循环节如果是a的因子,乘以a的该循环节长度就可以了,注意多个因子应该加在一起在往答案上乘
代码:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<string>
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cstring>
using namespace std;
#define LL long long
int a[100005];
int b[100005];
LL lenb[100005];
bool vis[100005] = {false};
const LL MOD = 1e9+7;
LL Dfs(int i,int num[])
{
vis[i] = true;
int id = num[i];
if(vis[id])return 1;
return Dfs(id,num)+1;
}
int main()
{
int n,m;
int _case = 0;
while(scanf("%d%d",&n,&m)!=EOF)
{
memset(lenb,0,sizeof(lenb));
for(int i = 0;i<n;i++)
{
scanf("%d",&a[i]);
}
for(int i = 0;i<m;i++)
{
scanf("%d",&b[i]);
}
vector<int>lena;
memset(vis,0,sizeof(vis));
for(int i = 0;i<n;i++)
{
if(!vis[i])
lena.push_back(Dfs(i,a));
}
memset(vis,0,sizeof(vis));
for(int i = 0;i<m;i++)
{
if(!vis[i])
{
lenb[Dfs(i,b)]++;
}
}
LL fans = 1;
for(int i = 0;i<lena.size();i++)
{
LL ans = 0;
for(int j = 1;j<=lena[i];j++)
{
if(lena[i]%j==0)
{
if(lenb[j]>0)
{
ans += j*lenb[j];
}
}
}
ans%=MOD;
fans *= ans;
fans%=MOD;
}
printf("Case #%d: %lld\n",++_case,fans);
}
return 0;
}