• P4980 【模板】Polya定理


    思路

    polya定理的模板题,但是还要加一些优化
    题目的答案就是

    [frac{sum_{i=1}^n n^{gcd(i,n)}}{n} ]

    考虑上方的式子怎么求

    因为(gcd(i,n))肯定有很多重复,枚举(gcd(i,n)),因为(gcd(i,n))(n)的约数,所以枚举约数

    [egin{align}&sum_{d|n}^nn^dsum_{k=1}^n[gcd(n,k)=d]\=&sum_{d|n}^nn^dsum_{k=1}^{lfloorfrac{n}{d} floor}[gcd(lfloorfrac{n}{d} floor,k)=1]\=&sum_{d|n}^nn^dphi(lfloorfrac{n}{d} floor) end{align} ]

    然后做完了

    一个求phi的方式

    (phi(i)=iprod_{p是k的质因数}(1-frac{1}{p}))

    如果有(p|n)(p^2|n),则(phi(n)=phi(n/p) imes p)
    如果有(p|n)(p^2 ot|n),则(phi(n)=phi(n/p) imes (p-1))

    代码

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <cmath>
    #define int long long
    using namespace std;
    int n,p,t,ans=0;
    int pow(int a,int b){
        int ans=1;
        while(b){
            if(b&1)
                ans=(ans*a)%p;
            a=(a*a)%p;
            b>>=1;
        }
        return ans;
    }
    int get_phi(int x){
        int ans=x;
        int top=sqrt(x+0.5);
        for(int i=2;i<=top;i++){
            if(x%i==0){
                ans=ans/i*(i-1);
                while(x%i==0)
                    x/=i;
            }
        }
        if(x!=1)
            ans=ans/x*(x-1);
        return ans;
    }
    signed main(){
        scanf("%d",&t);
        p=1000000007;
        while(t--){
            scanf("%lld",&n);
            ans=0;
            int top=sqrt(n+0.5);
            for(int i=1;i<=top&&i*i!=n;i++){
                if(n%i==0){
                    ans=(ans+pow(n,i)*get_phi(n/i)%p+pow(n,n/i)*get_phi(i)%p)%p;
                }
            }
            if(top*top==n)
                ans=(ans+pow(n,top)*get_phi(top)%p)%p;
            printf("%lld
    ",ans*pow(n,p-2)%p);
        }
    }
    
  • 相关阅读:
    浅谈P2P
    一串字符的解密
    下载地址解密
    初探DirectX
    本文介绍在VC 6.0中编译和使用OpenSSL的过程
    鱼钩绑线视频
    PKCS cer 证书
    02、创建顶点缓冲
    [原]SSL 开发简述(Delphi)
    [转]Delphi和C++数据类型对照表
  • 原文地址:https://www.cnblogs.com/dreagonm/p/10595903.html
Copyright © 2020-2023  润新知