其实很久以前就做过了 还是安利这里
可以发现当只有两种颜色时就是本质不同的无向图的个数
以下来自JYT的ppt
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=65;
ll fac[N],inv[N];
int n,m,P;
inline int Pow(ll a,int b) {
ll ret=1; for (;b;b>>=1,a=a*a%P) if (b&1) (ret*=a)%=P; return ret;
}
inline void Pre(int maxn){
fac[0]=1; for (int i=1;i<=maxn;i++) (fac[i]=i*fac[i-1])%=P;
inv[1]=1; for (int i=2;i<=maxn;i++) (inv[i]=(P-P/i)*inv[P%i])%=P;
inv[0]=1; for (int i=1;i<=maxn;i++) (inv[i]*=inv[i-1])%=P;
}
ll ans;
int cnt,val[N],num[N];
inline void dfs(int now,int left){
if (left==0){
ll ret=0,bot=1;
for (int i=1;i<=cnt;i++){
ret+=num[i]*(num[i]-1)/2*val[i]+val[i]/2*num[i];
for (int j=i+1;j<=cnt;j++)
ret+=num[i]*num[j]*__gcd(val[i],val[j]);
}
for (int i=1;i<=cnt;i++)
(bot*=Pow(val[i],num[i])*fac[num[i]]%P)%=P;
(bot=Pow(bot,P-2)*fac[n])%=P;
(ans+=Pow(m,ret)*bot%P)%=P;
return;
}
if (now>left) return;
dfs(now+1,left);
for (int i=1;i*now<=left;i++){
val[++cnt]=now; num[cnt]=i;
dfs(now+1,left-now*i);
cnt--;
}
}
int main(){
freopen("t.in","r",stdin);
freopen("t.out","w",stdout);
scanf("%d%d%d",&n,&m,&P);
Pre(60);
dfs(1,n);
printf("%d\n",ans*inv[n]%P);
return 0;
}