题解 P5233 [JSOI2012]爱之项链
洛谷题面传送门
首先很明显题目暗示我们先求出符合条件的戒指数量,再计算出由这些戒指能够构成的项链的个数,因此考虑分别计算它们。首先是计算符合条件的戒指数量,题目中“可以通过旋转重合的戒指视作相同”可以让我们联想到 Polya 定理,具体来说根据 Polya 那套理论,符合条件的戒指个数就是
接下来考虑此题的第二部分,如何通过符合条件的戒指数量
u1s1 感觉此题和这题出奇地相似,题解写得也出奇地相似(
ll n,MMOD=MOD;int m,r;
ll getmul(ll x,ll y){return (__int128_t)(1)*x*y%MMOD;}
int qpow(int x,ll e){
int ret=1;
for(;e;e>>=1,x=1ll*x*x%MOD) if(e&1) ret=1ll*ret*x%MOD;
return ret;
}
ll _qpow(int x,int e){
ll ret=1;
for(;e;e>>=1,x=getmul(x,x)) if(e&1) ret=getmul(ret,x);
return ret;
}
void exgcd(ll x,ll y,ll &a,ll &b){
if(!y) return a=1,b=0,void();exgcd(y,x%y,a,b);
ll tmp=a;a=b;b=tmp-(x/y)*b;
}
ll getinv(ll a,ll mod){
ll x,y;exgcd(a,mod,x,y);
return (x+mod)%mod;
}
int getphi(int x){
int res=x,tmp=x;
for(int i=2;i*i<=x;i++) if(tmp%i==0){
res=res/i*(i-1);
while(tmp%i==0) tmp/=i;
} if(tmp>1) res=res/tmp*(tmp-1);
return res;
}
int main(){
scanf("%lld%d%d",&n,&m,&r);ll ret=0;
bool flg=0;if(m%MOD==0) flg=1,MMOD=1ll*MOD*MOD;
for(int i=1;i*i<=m;i++) if(m%i==0){
ret=(ret+getmul(_qpow(r,i),getphi(m/i)))%MMOD;
if(m/i!=i) ret=(ret+getmul(_qpow(r,m/i),getphi(i)))%MMOD;
} ret=1ll*ret*getinv((flg)?(m/MOD):m,MMOD)%MMOD;
if(flg) ret/=MOD,ret%=MOD;
printf("%d\n",(1ll*(ret-1)*qpow((MOD-1),n)%MOD+qpow(ret-1,n))%MOD);
return 0;
}