• 【hdu 6038】Function


    Link:http://codeforces.com/contest/834/problem/C

    Description

    给你两个排列a和b;
    a排列的长度为n,b排列的长度为m;
    a∈[0..n-1],b∈[0..m-1];
    然后让你求一个函数f[i];
    f[i]的定义域为0..n-1,值域为0..m-1
    同时使得对于任意f[i],i∈[0..n-1];
    f(i)=bf(a[i])成立;

    Solution

    原始可以递推一下;
    f(i)=bf(ai)=bbf(aai)
    则可以一直写下去f[i]=bbbbbf(aaaaa[i]);
    注意到a是一个排列;
    最后肯定能形成一个环,则aaaaa..a[i]肯定又能变回i

    f(i)=bbf(i)��l times b
    (这里L是第一次回到i的L);
    这里的含义其实就相当于f[i]是一个x
    要使得
    x=b....bx
    而b也是一个排列;
    也肯定有循环节;
    这里从x开始的b数组的循环节长度一定得是上面的a的循环节的长度L的因子;
    不然就不能在L次b之后回到x了;
    于是,
    a数组里找循环节的长度,在b数组中也找循环节的长度;
    看看有多少个长度在a中有,且b数组中,有它的因子长度的循环节;
    直接累加因子循环节长度到temp中;
    然后累乘所有temp即可;
    根据上面的形式,每个a循环节中的某一个位置,f只要确定了,其他该循环节中的f值也就确定了,然后那个位置有temp种选择;就是因子循环节中任意一个b[i]都可以;
    找因子的时候,需要做些优化;
    不然可能退成O(n2)的复杂度;
    先枚举a数组有哪些循环节,长度为i;
    然后用O(i12)复杂度枚举它可能的因子,(j是则n/j也是)
    看看在b中有没有这样长度的;

    NumberOf WA

    0

    Reviw

    求因子的思想很好.

    Code

    #include <bits/stdc++.h>
    using namespace std;
    #define int long long
    
    const int N = 1e5;
    const int MOD = 1e9+7;
    
    int n,m;
    int a[N+10],b[N+10],cnta[N+10],cntb[N+10];
    bool flag[N+10];
    
    main(){
        int kk = 0;
        while (~scanf("%lld%lld",&n,&m)){
            for (int i = 1;i <= n;i++){
                scanf("%lld",&a[i]);
                a[i]++;
            }
            for (int i = 1;i <= m;i++){
                scanf("%lld",&b[i]);
                b[i]++;
            }
    
            memset(cnta,0,sizeof cnta);
            memset(cntb,0,sizeof cntb);
    
            memset(flag,0,sizeof flag);
            for (int i = 1;i <= m;i++)
                if (!flag[i]){
                    int x = i,num = 0;
                    while (!flag[x]){
                        flag[x] = 1;
                        num++;
                        x = b[x];
                    }
                    cntb[num]++;
                }
            memset(flag,0,sizeof flag);
            for (int i = 1;i <= n;i++)
                if (!flag[i]){
                    int x = i,num = 0;
                    while (!flag[x]){
                        flag[x] = 1;
                        num++;
                        x = a[x];
                    }
                    cnta[num]++;
                }
    
            int ans = 1;
            for (int i = 1;i <= n;i++)
            if (cnta[i]>0){
                int temp = 0;
                for (int j = 1;j*j <= i;j++)
                    if (i%j==0){
                        temp = (temp + j*cntb[j])%MOD;
                        if (j != i/j)
                            temp = (temp + (i/j)*cntb[i/j])%MOD;
                    }
                while (cnta[i]--){
                    ans = (ans*temp)%MOD;
                }
            }
            printf("Case #%lld: %lld
    ",++kk,ans);
        }
        return 0;
    }
  • 相关阅读:
    javascript数组查重方法总结
    html5的web存储
    掌握javascript中的最基础数据结构-----数组
    ES解决geoip的location不为geo_point格式
    elk默认分片只有1000导致索引没有创建
    Polysh批量管理服务器
    Git永久删除文件和历史记录
    windows下设置JupyterNotebook默认目录
    windwos安装RabbitMQ
    win7计划任务报该任务映像己损坏或己篡改
  • 原文地址:https://www.cnblogs.com/AWCXV/p/7626148.html
Copyright © 2020-2023  润新知