POJ2154Color Pólya定理+欧拉函数

Posted CQzhangyu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ2154Color Pólya定理+欧拉函数相关的知识,希望对你有一定的参考价值。

【POJ2154】Color

题意:求用$n$种颜色染$n$个珠子的项链的方案数。在旋转后相同的方案算作一种。答案对$P$取模。
询问次数$\le 3500$,$n\le 10^9,P\le 30000$
题解:旋转i次的循环个数显然是$gcd(i,n)$,然后套用Pólya定理。
$$ans=\frac 1 n \sum\limits_{i=1}^nn^{gcd(i,n)}$$
$$ans=\sum\limits_{i=1}^nn^{gcd(i,n)-1}$$
$$ans=\sum\limits_{i=1}^n\sum\limits_{d|n}n^{d-1}[gcd(i,n)=d]$$
$$ans=\sum\limits_{d|n}n^{d-1}\sum\limits_{i=1}^{n\over d}[gcd(i,{n\over d})=1]$$
$$ans=\sum\limits_{d|n}n^{d-1}\varphi({n\over d})$$
枚举约数即可。

#include <cstring>
#include <iostream>
#include <cstdio>
using namespace std;
const int maxn=100010;
typedef long long ll;
int n,P,T,m,ans;
int cnt[100],pri[100];
inline int phi(int x)
{
    int i,ret=1;
    for(i=2;i*i<=x;i++) if(x%i==0)
    {
        ret=ret*(i-1),x/=i;
        while(x%i==0)   ret=ret*i,x/=i;
    }
    if(x>1) ret=ret*(x-1);
    return ret;
}
inline int pw(int x,int y)
{
    x%=P;
    int z=1;
    while(y)
    {
        if(y&1) z=z*x%P;
        x=x*x%P,y>>=1;
    }
    return z;
}
void dfs(int x,int d)
{
    if(x==m+1)
    {
        ans=(ans+phi(n/d)%P*pw(n,d-1))%P;
        return ;
    }
    for(int i=0;i<=cnt[x];i++,d*=pri[x])    dfs(x+1,d);
}
void work()
{
    scanf("%d%d",&n,&P),ans=m=0;
    int i,t=n;
    for(i=2;i*i<=t;i++) if(t%i==0)
    {
        cnt[++m]=0,pri[m]=i;
        while(t%i==0)   t/=i,cnt[m]++;
    }
    if(t>1) pri[++m]=t,cnt[m]=1;
    dfs(1,1);
    printf("%d\n",ans);
}
int main()
{
    scanf("%d",&T);
    while(T--)  work();
    return 0;
}//1 2 30000

以上是关于POJ2154Color Pólya定理+欧拉函数的主要内容,如果未能解决你的问题,请参考以下文章

Burnside 引理 & Pólya 定理

置换及Pólya定理

poj2154Color Polya定理+欧拉函数

Burnside 引理 / Pólya 定理

POJ2154 Color polya定理+欧拉定理

BZOJ1478Sgu282 Isomorphism Pólya定理神题