Polya定理模板

相信很多初学者刚接触Polya定理的时候一脸懵逼,因为它以许多离散数学的知识为基础,所以不太好上手,所以我在这里把模板贴出来。

Polya定理是用来求出m种颜色涂入n个对象一共有多少种方法的一种定理。

暴力版模板

#include<iostream>  
#include<cstdio>  
#include<cmath>  
using namespace std;  
typedef long long LL;  
int gcd(int a,int b)  
{  
    if(b==0) return a;  
    return gcd(b,a%b);  
}  
LL polya(int m,int n)  //m color ,n number  
{  
    LL tot=0;  //方案数   
    for(int i=1;i<=n;i++)  
        tot+=pow(m,gcd(n,i));  
    tot/=n;   
    if(n%2!=0) tot+=pow(m,(n+1)/2); //odd  
    else tot+=(pow(m,n/2)+pow(m,n/2+1))/2;  
    return tot/2;  
}



还有一种欧拉函数优化版

时间复杂度是O(sqrt(n))

#include<iostream>  
#include<cstdio>  
#include<cmath>  
using namespace std;  
typedef long long LL;  
int gcd(int a,int b)  
{  
    if(b==0) return a;  
    return gcd(b,a%b);  
}  
int euler_phi(int n)  
{  
    int res=1;  
    for(int i=2;i*i<=n;i++)  
    if(n%i==0) {         //说明i|n  
        n/=i,res*=i-1;  
        while(n%i==0) n/=i,res*=i;  //说明i^2|n  
    }  
    if(n>1) res*=n-1;  
    return res;  
}  
LL polya(int m,int n)  //m color ,n number  
{  
    LL tot=0;  //方案数   
    for(int i=1;i*i<=n;i++)    //1~sqrt(n)  
    {  
        if(n%i) continue;    //当i不是n的约数时就进入下一次循环   
        tot+=euler_phi(i)*pow(m,n/i);  //d=gcd(n,i) d为n的因数,且有euler_phi(n/i)个   
        if(i*i!=n) tot+=euler_phi(n/i)*pow(m,i); //当i*i==n时,不必算两次   
    }  
    tot/=n;   
    if(n%2!=0) tot+=pow(m,(n+1)/2); //odd  
    else tot+=(pow(m,n/2)+pow(m,n/2+1))/2;  
    return tot/2;  
}  



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值