记录一个菜逼的成长。。
2017 Multi-University Training Contest - Team 1
题目链接
题目大意:
给你长度为
n
的的
求有多少种函数满足
fi=bfai
笔记(官方题解
考虑置换
a
的循环节,长度为
那么
fi
的值在置换
b
中所在的循环节的长度必须为
而如果 fi 值确定下来了,这个循环节的另外 l−1 个数的函数值也都确定下来了。
答案就是
∏ki=1∑j|lij∗calj
.其中
k
是置换
#include <bits/stdc++.h>
using namespace std;
#define rep(i,l,r) for( int i = l; i <= r; i++ )
#define rep0(i,l,r) for( int i = l; i < r; i++ )
#define ALL(v) (v).begin(),(v).end()
#define cl(a,b) memset(a,b,sizeof(a))
#define clr clear()
#define pb push_back
#define mp make_pair
#define fi first
#define se second
typedef long long LL;
typedef pair<int,int> PII;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const int maxn = 100000 + 10;
int a[maxn],b[maxn],vis[maxn];
int cnt[maxn],fa[maxn];
int main()
{
int cas = 1,n,m;
while(~scanf("%d%d",&n,&m)){
rep(i,1,n)scanf("%d",a+i),a[i]++;
rep(i,1,m)scanf("%d",b+i),b[i]++;
cl(vis,0);
int len = 0;
//计算a的循环节
rep(i,1,n){
int l = 0,ind = a[i];
while(!vis[a[ind]]){
vis[a[ind]] = 1;
l++;ind = a[ind];
}
if(l)fa[len++] = l;
}
cl(vis,0);cl(cnt,0);
//统计b的循环节的长度数量
rep(i,1,m){
int l = 0,ind = b[i];
while(!vis[b[ind]]){
vis[b[ind]] = 1;
l++;ind = b[ind];
}
if(l)cnt[l]++;
}
LL ans = 1;
rep0(i,0,len){
int num = fa[i];
LL sum = 0;
int k = sqrt(num + 0.5);
for( int j = 1; j <= k; j++ ){
if(num % j == 0){
sum += j * cnt[j];
sum %= MOD;
if(num/j != j){
sum += num/j * cnt[num/j];
sum %= MOD;
}
}
}
ans = ans * sum % MOD;
}
printf("Case #%d: %lld\n",cas++,ans);
}
return 0;
}