P4980 【模板】Pólya 定理

作为板子题,先上公式:

\[|X/G|=\frac 1{|G|}\sum_{g\in G} |B|^{c(g)} \]

显然,\(|G|=n\)

\(g_i\) 表示旋转 \(i\) 个的置换,则 \(c(g_i)=(n,i)\)

我们要算下式:

\[\begin{aligned} &\frac 1n\sum_{i=1}^n n^{(n,i)} \\ =&\frac 1n\sum_ {d\mid n} n^d\cdot \sum_{i=1}^n [(n,i)=d] \\ =&\frac 1n\sum_{d\mid n} n^d\cdot \varphi(\frac nd) \end{aligned}\]

本题中直接暴力计算 \(\varphi\) 可以通过。

分析复杂度可参见本文

复杂度 \(\mathcal O(Tn^{\frac 34})\)

或者考虑利用该博客中的法二计算。

但考虑到实际上 \(d(n)\) 远小于 \(\sqrt n\)(当 \(n\) 足够大时,\(d(n)\cdot \log n\) 也小于 \(\sqrt n\)),所以法二的单次复杂度就是 \(\mathcal O(\sqrt n)\) 的。

我的程序使用方法二,复杂度 \(\mathcal O(T\sqrt n)\)

$\textsf {View Code}$
#include <cstdio>
#include <cctype>
#include <algorithm>
using namespace std;
char buf[1<<14],*p1=buf,*p2=buf;
#define GetC() ((p1==p2)&&(p2=(p1=buf)+fread(buf,1,1<<14,stdin),p1==p2)?EOF:*p1++)
struct Ios{}io;
template <typename _tp>
Ios &operator >>(Ios &in,_tp &x){
	x=0;int w=0;char c=GetC();
	for(;!isdigit(c);w|=c=='-',c=GetC());
	for(;isdigit(c);x=x*10+(c^'0'),c=GetC());
	if(w) x=-x;
	return in;
}
const int mod=1e9+7,N=30;
using ll=long long;
ll qpow(ll a,int b){
	ll ans=1;
	while(b){
		if(b&1) ans=ans*a%mod;
		b=b>>1;a=a*a%mod;
	}
	return ans;
}
int q[N],num[N],cnt;
int ans,n;
void dfs(int stp,int d,int phi){
	if(stp>cnt){
		ans=(ans+qpow(n,n/d)*phi%mod)%mod;
		return ;
	}
	dfs(stp+1,d,phi);
	int t=1;
	for(int i=1;i<=num[stp];++i){
		dfs(stp+1,d*t*q[stp],phi*t*(q[stp]-1));
		t*=q[stp];
	}
}
int main(){
	int T;io>>T;
	while(T--){
		io>>n;
		cnt=0;
		int tmp=n;
		for(int i=2;1ll*i*i<=n;++i){
			if(n%i==0){
				q[++cnt]=i;
				num[cnt]=0;
				while(n%i==0) n/=i,++num[cnt];
			}
		}
		if(n>1){
			q[++cnt]=n;num[cnt]=1;
		}
		n=tmp;
		dfs(1,1,1);
		printf("%lld\n",(ll)ans*qpow(n,mod-2)%mod);
		ans=0;
	}
	return 0;
}
posted @ 2023-01-12 20:02  pref_ctrl27  阅读(24)  评论(0编辑  收藏  举报