题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=6038
代码:
#include <cstdio>
#include <stack>
#include <map>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define met(a,b) memset(a,b,sizeof(a))
#define inf 0x3f3f3f3f
const int maxn = 1e5+10;
const int mod =1e9+7;
typedef long long ll;
stack<int> s;
vector<int> v[maxn];
bool instack[maxn];
int dfn[maxn],low[maxn];
int belong[maxn];//缩点存储
int degree[maxn];
int cnt1;//更新
int cnt2;//计算有几个满足条件
int num1[maxn],num2[maxn];
map<int,int> mp2;
int length;
int n,m;
int a[maxn],b[maxn];
int ans[maxn];
void scc(int x)
{
dfn[x]=low[x]=cnt1++;
instack[x]=true;
s.push(x);
for(int i=0;i<v[x].size();i++)
{
int y=v[x][i];
if(dfn[y]==-1)
{
scc(y);
low[x]=min(low[x],low[y]);
}
else if(instack[y])
{
low[x]=min(low[x],dfn[y]);
}
}
if(dfn[x]==low[x])
{
int z;
do
{
z=s.top();
s.pop();
instack[z]=false;
belong[z]=cnt2;
}
while(x!=z);
cnt2++;
}
}
void Tarjan(int x)
{
while(!s.empty())
s.pop();
met(dfn,-1);
met(low,inf);
met(belong,-1);
met(instack,false);
cnt1=0;
cnt2=0;
for(int i=0;i<x;i++)
{
if(dfn[i]==-1)
scc(i);
}
}
void slove1()
{
Tarjan(n);
met(num1,0);
for(int i=0;i<n;i++)
num1[belong[i]]++;
length=cnt2;
}
void slove2()
{
Tarjan(m);
met(num2,0);
for(int i=0;i<m;i++)
num2[belong[i]]++;
mp2.clear();
for(int i=0;i<cnt2;i++)
mp2[num2[i]]+=num2[i];
}
int main()
{
int id=1;
while(scanf("%d%d",&n,&m)!=EOF)
{
for(int i=0;i<n;i++)
{
scanf("%d",&a[i]);
v[i].clear();
}
for(int i=0;i<n;i++)
v[a[i]].push_back(i);
slove1();
for(int i=0;i<m;i++)
{
scanf("%d",&b[i]);
v[i].clear();
}
for(int i=0;i<m;i++)
v[b[i]].push_back(i);
slove2();
met(ans,0);
for(int i=0;i<length;i++)
{
for(int j=1;j*j<=num1[i];j++)
{
if(num1[i]%j==0)
{
ans[i]+=mp2[j];
if(j*j!=num1[i])
ans[i]+=mp2[num1[i]/j];
}
}
}
ll sum=1;
for(int i=0;i<length;i++)
sum=(sum*ans[i])%mod;
printf("Case #%d: ",id++);
printf("%lld\n",sum);
}
}