hdu 6038 Function (思维题搞一搞)

来源:互联网 发布:vue.js 格式化数字 编辑:程序博客网 时间:2024/06/06 12:49

f函数的限制关系形成多个环,b的排列也形成多个循环。f中每个环要合法赋值,环的大小要能被b的某个环的大小整除,方案为b环的大小

。再把f每个环的赋值方案相乘就是答案。例如f有环4,6,8。b环 2,3。ans= (2 )* (2 + 3)*(2)

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <set>using namespace std;typedef long long ll;const ll md = 1e9 + 7;const int MAXN = 1e5 + 10;int fa1[MAXN], fa2[MAXN];int sum1[MAXN], sum2[MAXN];set<int>st1, st2;int find1(int x){    return fa1[x] == x ? x : (fa1[x] = find1(fa1[x]));}void merge1(int x, int y){    x = find1(x);    y = find1(y);    if (x != y){        fa1[x] = y;        sum1[y] += sum1[x];    }}int find2(int x){    return fa2[x] == x ? x : (fa2[x] = find2(fa2[x]));}void merge2(int x, int y){    x = find2(x);    y = find2(y);    if (x != y){        fa2[x] = y;        sum2[y] += sum2[x];    }}int n, m;int p[MAXN], q[MAXN];int val[MAXN];void init(){    for (int i = 0; i < n; i++){        fa1[i] = i;        sum1[i] = 1;    }    for (int i = 0; i < m; i++){        fa2[i] = i;        sum2[i] = 1;    }    memset(val, 0, sizeof(val));    st1.clear();    st2.clear();}int main(){    int cas = 1;    while (scanf("%d%d", &n, &m) != EOF){        init();        for (int i = 0; i < n; i++)            scanf("%d", &p[i]);        for (int i = 0; i < m; i++){            scanf("%d", &q[i]);        }        for (int i = 0; i < n; i++){            merge1(i, p[i]);        }        for (int i = 0; i < m; i++){            merge2(i, q[i]);        }        for (int i = 0; i < n; i++){            if (find1(i) == i){                st1.insert(i);            }        }        int MAX = 0;        for (int j = 0; j < m; j++){            if (find2(j) == j){                st2.insert(sum2[j]);                val[sum2[j]]++;                MAX = max(MAX, sum2[j]);            }        }        ll ans = 1;        ll tmp = 0;        set<int>::iterator it, it2;        for (it = st1.begin(); it != st1.end(); it++){            tmp = 0;            for (it2 = st2.begin(); it2 != st2.end(); it2++){                int big = *it2;                if (sum1[*it] % (*it2) == 0){                    tmp += (*it2)*val[*it2];                    tmp %= md;                }                /*for (int j = 1; j*j <= big; j++){                    if (sum1[*it] % j == 0){                        ans += (ll)j *val[*it];                        ans %= md;                        if (j*j == big)break;                    }                }*/            }            ans = ans * tmp;            ans %= md;        }        printf("Case #%d: %lld\n", cas++, ans);    }}
原创粉丝点击