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\n",++CC,ans);}
}