[POJ2154] Color [Polya定理][莫比乌斯反演]

题意:

从N种颜色的珠子中选出N个串成一圈,问有多少种方案。(不考虑翻转)

读入X(X <= 3500)
对于X组数据,每一组给出N(1 <= N <= 1000000000)和P(1 <= P <= 30000),要求输出Ans%P

环是可以旋转的(本题不考虑翻转)

显然是置换。

有N种置换(包括不转动);

第i种置换(也就是旋转了i格)有 r = g c d ( N , i ) r=gcd(N,i) r=gcd(N,i)个循环

根据Polya定理有 A n s = ∑ N r N = ∑ N ( g c d ( N , i ) ) N = ∑ N ( g c d ( N , i ) − 1 ) Ans=\frac{\sum N^{r}}{N}=\frac{\sum N^{(gcd(N,i))}}{N}=\sum N^{(gcd(N,i)-1)} Ans=NNr=NN(gcd(N,i))=N(gcd(N,i)1)

每次Euclid求gcd复杂度 O (   lg ⁡ &ThinSpace; i   ) O(\ \lg\,i\ ) O( lgi )

快速幂复杂度 O (   log ⁡ 2 N   ) O(\ \log_2\sqrt N\ ) O( log2N  )

总复杂度 O ( N ∗ ( lg ⁡ i &ThinSpace; + &ThinSpace; log ⁡ 2 N ) O(N*(\lg i\,+\,\log_2\sqrt N) O(N(lgi+log2N )

好像十分完美

可是我们想想这道题还有个X

总复杂度应该是 O ( X ∗ N ∗ ( lg ⁡ i &ThinSpace; + &ThinSpace; log ⁡ 2 N ) O(X*N*(\lg i\,+\,\log_2\sqrt N) O(XN(lgi+log2N )

凉凉


我们前面得到了 A n s = ∑ N ( g c d ( N , i ) − 1 ) Ans=\sum N^{(gcd(N,i)-1)} Ans=N(gcd(N,i)1)

有sum有gcd,思考利用莫比乌斯反演进行优化

如果 F ( n ) = ∑ d ∣ N f ( d ) F(n)=\sum_{d|N}f(d) F(n)=dNf(d),有 f ( n ) = ∑ d ∣ N μ ( d ) F ( N d ) f(n)=\sum_{d|N}μ(d)F(\frac{N}{d}) f(n)=dNμ(d)F(dN)

由于N为正整数,有 ∑ d ∣ N μ ( d ) d = ϕ ( N ) N \sum_{d|N}\frac{μ(d)}{d}=\frac{\phi(N)}{N} dNdμ(d)=Nϕ(N)

显然 A n s = ∑ ( d ∣ N ) {   N d ∗ ∑ k = 0 N [   d = g c d ( K , N )   ]   } Ans=\sum_{(d|N)}\{\ N^{d}*\sum_{k=0}^N[\ d=gcd(K,N)\ ]\ \} Ans=(dN){ Ndk=0N[ d=gcd(K,N) ] }

F ( n ) = ∑ ( d ∣ N ) f ( n ) &ThinSpace; , &ThinSpace; f ( n ) = N d F(n)=\sum_{(d|N)}f(n)\,,\,f(n)=N^d F(n)=(dN)f(n),f(n)=Nd

N d = ∑ ( d ∣ N ) ϕ ( N ) N ∗ ∑ ( d ∣ N ) N d d N^d=\sum_{(d|N)}\frac{\phi(N)}{N}*\sum_{(d|N)}\frac{N^d}{d} Nd=(dN)Nϕ(N)(dN)dNd


A n s = ∑ ( d ∣ N ) N d − 1 ∗ ∑ k = 0 ( N − 1 ) (   g c d ( K , N ) d = 1   ) Ans=\sum_{(d|N)}N^{d-1}*\sum_{k=0}^{(N-1)}(\ \frac{gcd(K,N)}{d}=1\ ) Ans=(dN)Nd1k=0(N1)( dgcd(K,N)=1 )

= ∑ ( d ∣ N ) N d − 1 ∗ ∑ k = 0 ( N − 1 ) (   g c d ( K d , N d ) = 1   ) \qquad=\sum_{(d|N)}N^{d-1}*\sum_{k=0}^{(N-1)}(\ gcd(\frac{K}{d},\frac{N}{d})=1\ ) =(dN)Nd1k=0(N1)( gcd(dK,dN)=1 )

= ∑ ( d ∣ N ) N d − 1 ∗ ∑ k = 0 ( N d − 1 ) (   g c d ( K , N d ) = 1   ) \qquad=\sum_{(d|N)}N^{d-1}*\sum_{k=0}^{(\frac{N}{d}-1)}(\ gcd(K,\frac{N}{d})=1\ ) =(dN)Nd1k=0(dN1)( gcd(K,dN)=1 )

注意到右边等于 ϕ ( N d ) \phi(\frac{N}{d}) ϕ(dN)

A n s = ∑ ( d ∣ N ) N d − 1 ∗ ϕ ( N d ) Ans=\sum_{(d|N)}N^{d-1}*\phi(\frac{N}{d}) Ans=(dN)Nd1ϕ(dN)

求欧拉函数因为要mod p就没办法线性筛了有点遗憾(

不过我们可以线性筛素数,用分解质因数的方法枚举素数求出 Φ \Phi Φ

最后mod不是问题,直接%就好,因为前面已经把除N搞掉了

和p也不一定互质,没办法用什么逆元(


感觉做了一道假的polya

Code:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<cctype>
using namespace std;
#define LL long long
const int Limit=sqrt(1e9);
int Primetot=0;
int X,N,P;
int Ans;
LL Phi[32767]={};
int Prime[32767]={};
bool notPrime[32767]={};
int Quick_Pow(int Num,int Pow)
{
	register int Base=Num%P;
	int Res=1;
	while(Pow)
	{
		if(Pow&1)Res=Res*Base%P;
		Base=Base*Base%P;
		Pow>>=1;
	}
	return Res;
}
int phi(int Num)
{
	register int Res=Num;
	for(int i=1;Prime[i]<=sqrt(Num);++i)
	{
		if(Num%Prime[i])continue;
		Res-=Res/Prime[i];
		while(Num%Prime[i]==0)Num/=Prime[i];
	}
	if(Num!=1)Res-=Res/Num;
	return Res%P;
}
int main()
{
	scanf("%d",&X);
	for(int i=2;i<=Limit;++i)
	{
		if(notPrime[i])continue;
		for(int j=2;i*Prime[j]<=Limit&&j<=Primetot;++j)
		{
			notPrime[i*Prime[j]]=1;
			if(i%Prime[j]==0)
			{
				notPrime[i]=1;
				break;
			}
		}
		if(!notPrime[i])Prime[++Primetot]=i;
	}
	while(X--)
	{
		register int i;
		Ans=0;
		scanf("%d%d",&N,&P);
		for(i=1;i*i<=N;++i)
		{
			if(N%i==0)
			{
				Ans+=Quick_Pow(N,i-1)*phi(N/i);
				if(i*i!=N)Ans+=Quick_Pow(N,N/i-1)*phi(i);
				Ans%=P;
			}
		}
		printf("%d\n",Ans);
	}
	return 0;
}

上面是一两年前写的
然后呢 里面的莫反就是个套路
∑ k = 0 n − 1 n ( k , n ) − 1 \sum\limits_{k=0}^{n-1}n^{(k,n)-1} k=0n1n(k,n)1
∑ d ∣ n n d − 1 ∑ k = 0 n − 1 [ d = ( k , n ) ] \sum\limits_{d|n}n^{d-1}\sum\limits_{k=0}^{n-1}[d=(k,n)] dnnd1k=0n1[d=(k,n)]
∑ d ∣ n n d − 1 ∑ k = 0 n d − 1 [ ( k , n d ) = 1 ] \sum\limits_{d|n}n^{d-1}\sum\limits_{k=0}^{\frac{n}{d}-1}[(k,\frac{n}{d})=1] dnnd1k=0dn1[(k,dn)=1]
∑ d ∣ n ϕ ( n d ) n d − 1 \sum\limits_{d|n}\phi(\frac{n}{d})n^{d-1} dnϕ(dn)nd1
吸收一下思想?考虑到暴力计算的重复计算部分然后就大概有莫反的思路了
假如做得熟练,看出莫反就是一眼的事情了。。
然后本题的另一部分(环置换)也很经典啊。所以这道题是一道一眼大水题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值