题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6038
AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll a[100005],b[100005];
int n,m;
ll numa[100005],numb[100005];
int vis[100005];
const int mod=1e9+7;
void dfsa(int x,int sum)//求序列a中的循环节,并将每个循环节的大小存在numa中
{
if(vis[x])
{
numa[sum]++;
return ;
}
vis[x]=1;
dfsa(a[x],sum+1);
}
void dfsb(int x,int sum)//求序列b中的循环节,并将每个循环节的大小存在numb中
{
if(vis[x])
{
numb[sum]++;
return ;
}
vis[x]=1;
dfsb(b[x],sum+1);
}
int main()
{
int Case=0;
while(cin>>n>>m)
{
for(int i=0;i<n;i++)
scanf("%lld",&a[i]);
for(int i=0;i<m;i++)
scanf("%lld",&b[i]);
memset(vis,0,sizeof(vis));
memset(numa,0,sizeof(numa));
for(int i=0;i<n;i++)
{
if(vis[i]==0)
{
dfsa(i,0);
}
}
memset(vis,0,sizeof(vis));
memset(numb,0,sizeof(numb));
for(int i=0;i<m;i++)
{
if(vis[i]==0)
{
dfsb(i,0);
}
}
ll sum=1;
for(int i=1;i<=n;i++)
{
if(numa[i])//a中长度为i的循环节存在
{
ll tmp=0;
ll len=(ll)sqrt(i+0.5);
for(int j=1;j<=len;j++)
{
if(i%j==0)//遍历b序列中长度为numa[i]的因子的序列
{
tmp=(tmp+numb[j]*j%mod)%mod;//numb[j]*j表示b中长度为j的个数乘以循环节长度numb[j],即求和。
if(j*j!=i)
tmp=(tmp+numb[i/j]*(i/j)%mod)%mod;
}
}
for(int j=1;j<=numa[i];j++)//长度为numa[i]的循环节可能有多个
sum=(sum*tmp)%mod;
}
}
printf("Case #%d: %lld\n",++Case,sum);
}
return 0;
}
我一定可以的!!!