HDU6038 - Function
做法:
展开后有,(f(i) = b_{f(a_i)} = b_{b_{f(a_{a_i})}} = ... = b_{b_{..b_{f(i)}}}),可以发现当 (a_i) 所在的循环节中确定一个时,整个循环都确定了,根据这个式子还可以发现,对于一个(a_i)所在的大小为(x)的循环节,一定映射到一个(b_i)中的一个大小为(y)循环节,且(y|x) 。因此答案就是:
[prod_{i=1}^k sum_{d|l_i} d·B_d
]
(其中(a)有(k)个大小为(l_i)的循环节,扎着(b)中大小为(i)的循环节有 (B_i) 个)
#include <bits/stdc++.h>
typedef long long ll;
const int N = 1e5 + 7;
const int mod = 1e9 + 7;
using namespace std;
int n, m, a[N], b[N], in[N], CC = 0;
ll B[N];
ll cal(int st, int a[]) {
int now = st; ll ans = 0;
while(!in[now]) {
in[now] = 1;
now = a[now];
++ans;
}
return ans;
}
int main() {
while(scanf("%d%d",&n,&m)!=EOF) {
for(int i = 0; i < n; ++i) scanf("%d", &a[i]);
for(int i = 0; i < m; ++i) scanf("%d", &b[i]);
memset(B,0,sizeof(B));
memset(in,0,sizeof(in));
for(int i = 0; i < m; ++i) if(!in[i]) ++B[cal(i,b)];
memset(in,0,sizeof(in));
ll ans = 1LL;
for(int i = 0; i < n; ++i) if(!in[i]) {
ll x = cal(i,a), tmp = 0;
for(ll j = 1; j*j <= x; ++j) if(x%j == 0) {
(tmp += j*B[j]%mod)%=mod;
if(j*j==x) continue;
(tmp += ((x/j)*B[x/j])%mod)%=mod;
}
(ans *= tmp)%=mod;
}
printf("Case #%d: %lld
",++CC,ans);
}
}