传送门:https://www.luogu.org/problem/P2303
这道题要放在一个月前,一眼出答案。可惜,我全忘了.......所以只好翻出了学习Polya定理时的代码......温故一下
求 ∑gcd(i,n)
就直接看gcd(i,n)的数值有哪些。枚举1~n,它对应的个数就为φ(n/i)。
你可以优化到O(n1/2),这道题就完了。
#include<cstdio> #define R register using namespace std; typedef long long ll; ll n,ans; ll phi(ll x){ ll y=x,z=x; for(ll i=2;i*i<=x;i++){ if(x%i==0) y=(y/i)*(i-1); while(x%i==0) x/=i; } if(x>1) return y/x*(x-1); return y; } int main (){ scanf("%lld",&n); ll i=1; for(;i*i<n;i++){ if(n%i==0) ans+=i*phi(n/i)+(n/i)*phi(i); } if(i*i==n) ans+=i*phi(n/i); printf("%lld ",ans); return 0; }
Burnside定理: ans=1/n * ∑kf(k) f(k)为,在置换k下的不动点的个数。
Polya定理:f(k)=ap(k) a为颜色数,p(k)为循环节的个数。