• P4980 【模板】Polya定理


    P4980 【模板】Polya定理

    题目描述

    给定一个(n)个点,(n)条边的环,有(n)种颜色,给每个顶点染色,问有多少种本质不同的染色方案,答案对(10^9+7)取模

    注意本题的本质不同,定义为:只需要不能通过旋转与别的染色方案相同

    输入输出格式

    输入格式:

    第一行输入一个(t),表示有(t)组数据

    第二行开始,一共(t)行,每行一个整数(n),意思如题所示。

    输出格式:

    (t)行,每行一个数字,表示染色方案数对(10^9+7)取模后的结果

    说明

    (n leq 10^9,t leq 10^3)


    注意置换只有(n)个,表示旋转的度数,没有翻转。

    那么一个旋转(i)个点的置换的循环个数应该为(gcd(i,m))

    带到(Polya)定理里面去,方案数为

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

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

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

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

    [=sum_{k|n}n^{k-1}varphi(frac{n}{k}) ]

    然后直接暴力搞,复杂度是常数很小的(O(Tn^{frac{3}{4}}))


    Code:

    #include <cstdio>
    const int mod=1e9+7;
    int Euler(int n)
    {
        int phi=n;
        for(int i=2;i*i<=n;i++)
            if(n%i==0)
            {
                phi=phi-phi/i;
                while(n%i==0) n/=i;
            }
        if(n!=1) phi=phi-phi/n;
        return phi;
    }
    #define mul(a,b) (1ll*(a)*(b)%mod)
    #define add(a,b) ((a+b)%mod)
    int qp(int d,int k){int f=1;while(k){if(k&1)f=mul(f,d);d=mul(d,d),k>>=1;}return f;}
    int Polya(int n)
    {
        int ans=0;
        for(int i=1;i*i<=n;i++)
        {
            if(n%i) continue;
            ans=add(ans,mul(qp(n,i-1),Euler(n/i)));
            if(i*i!=n)
                ans=add(ans,mul(qp(n,n/i-1),Euler(i)));
        }
        return ans;
    }
    int main()
    {
        int n,T;
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d",&n);
            printf("%d
    ",Polya(n));
        }
        return 0;
    }
    

    2018.12.21

  • 相关阅读:
    虚方法与非虚方法,native关键字
    Java多态
    Java对象初始化顺序
    继承、初始化
    递归,斐波那契,对象类型数组
    方法重载
    可变形参
    idea
    ss 如何解决margin-top使父元素margin失效
    js中call和apply的用法和区别
  • 原文地址:https://www.cnblogs.com/butterflydew/p/10155264.html
Copyright © 2020-2023  润新知