题意:
外面有一圈N个结点,中心有一个结点与N个结点都相连,总共就是2*N条边,删除N条边,使N+1个点连通,旋转相同视为等价,问有多少种情况。
题解:
Burnside引理。
首先枚举公约数,找等价类。
对于一个等价类,矩阵树+打表发现
f(n)=3∗f(n−1)−f(n−2)+2
,直接矩阵快速幂。
要注意的是mod一个合数可能不存在逆元,稍加转化:
a=(k∗c+r)∗babmodc=r⇒amodbcb=r
再 O(1) 快速乘就好了:http://blog.youkuaiyun.com/qq_35649707/article/details/76732760
#include<iostream>
#include<cstdio>
using namespace std;
struct IO{
streambuf *ib,*ob;
inline void init(){
ios::sync_with_stdio(false);
cin.tie(NULL);cout.tie(NULL);
ib=cin.rdbuf();ob=cout.rdbuf();
}
template<typename T1>
inline bool read(T1 &x){
static char ch;static long long i,f;
ch=ib->sbumpc();i=0,f=1;
while(!isdigit(ch)){
if(ch==-1)return false;
if(ch=='-')f=-1;
ch=ib->sbumpc();
}
while(isdigit(ch)){
i=(i+(i<<2)<<1)+ch-'0';
ch=ib->sbumpc();
}
x=((f>0)?i:-i);
return true;
}
inline void W(long long x){
static long long buf[50];
if(!x){ob->sputc('0');return;}
if(x<0){ob->sputc('-');x=-x;}
while(x){buf[++buf[0]]=x%10;x/=10;}
while(buf[0]){ob->sputc(buf[buf[0]--]+'0');}
}
}io;
long long n;
long long mod;
long long ans;
inline long long mul(long long x,long long y)
{
return (x*y-(long long)((long double)x/mod*y)*mod+mod)%mod;
}
struct matrix{
long long a[4][4];
inline void init(long long val){
for(long long i=1;i<=3;i++)
for(long long j=1;j<=3;j++)
this->a[i][j]=0;
for(long long i=1;i<=3;i++)this->a[i][i]=val;
}
friend inline matrix operator *(const matrix &a,const matrix &b)
{
matrix c;c.init(0);
for(long long i=1;i<=3;i++)
for(long long j=1;j<=3;j++)
for(long long k=1;k<=3;k++)
(c.a[i][j]+=mul(a.a[i][k],b.a[k][j]))%=mod;
return c;
}
friend inline matrix operator ^(matrix a,long long b)
{
matrix c;c.init(1);
for(;b;b>>=1,a=a*a)
if(b&1)c=c*a;
return c;
}
}e;
inline long long getphi(long long x){
long long res=x;
for(long long b=2;b*b<=x;b++)
{
if(x%b)continue;
(res/=b)*=(b-1);
while(!(x%b))x/=b;
}
if(x!=1)(res/=x)*=(x-1);
return res;
}
inline long long calc(long long k){
if(k<3){return ((k==1)?1:5);}
matrix a;a.init(0);
a.a[1][1]=5,a.a[1][2]=1,a.a[1][3]=2;
a=a*(e^(k-2));
return a.a[1][1];
}
int main(){
io.init();e.init(0);
e.a[1][1]=3;e.a[1][2]=1;e.a[3][1]=1;e.a[3][3]=1;
while(io.read(n),io.read(mod)){
ans=0;mod*=n;
e.a[2][1]=mod-1;
for(long long d=1;d*d<=n;d++){
if(n%d)continue;
(ans+=(1ll*mul(getphi(n/d),calc(d))%mod))%=mod;
if(n/d!=d)(ans+=(1ll*mul(getphi(d),calc(n/d))%mod))%=mod;
}
io.W(ans/n);io.ob->sputc('\n');
}
}