HDU6038 - Function

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);
    }
}

posted @ 2018-09-25 15:35  RRRR_wys  阅读(133)  评论(0编辑  收藏  举报