题目大意:
给定一个
n
阶完全图,可以把每条边染成
分析:
这是论文题,给个讲的好点的链接吧:
http://endlesscount.blog.163.com/blog/static/8211978720122154253812/
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <climits>
#include <cmath>
#include <string>
#include <iostream>
#include <algorithm>
#include <set>
#include <map>
#include <list>
#include <queue>
#include <stack>
#define ONLINE_JUDGE
typedef long long LL;
typedef long double LD;
typedef double DB;
using namespace std;
const int MaxN = 69;
int Mod;
int n, m;
int inv[MaxN];
int L[MaxN];
int ans;
int Gcd[MaxN][MaxN];
int invl[MaxN];
int mi[MaxN*MaxN];
int PowerMod(int a, int b, int m)
{
int re = 1, base = a;
while(b)
{
if(b&1) re = (LL)re*base%m;
base = (LL)base*base%m;
b >>= 1;
}
return re;
}
#define Inv(a, b) (PowerMod(a, b-2, b))
int gcd(int a, int b)
{
if(b) return gcd(b, a%b);
else return a;
}
int calc(int m)
{
int re = 1;
for(int i = 1, l = 1; i <= m; ++i)
{
re = (LL)re*invl[L[i]]%Mod;
if(i == m || L[i] != L[i+1])
{
re = (LL)re*inv[l]%Mod;
l = 1;
}
else l++;
}
int num = 0;
for(int i = 1; i <= m; ++i)
{
num += L[i]/2;
for(int j = i+1; j <= m; ++j)
num += Gcd[L[i]][L[j]];
}
re = (LL)re*mi[num]%Mod;
return re;
}
void Dfs(int cnt, int sum)
{
L[cnt] = n-sum;
ans = (ans+calc(cnt))%Mod;
for(int i = L[cnt-1]; i*2 <= n-sum; ++i)
{
L[cnt] = i;
Dfs(cnt+1, sum+i);
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("sgu282.in", "r", stdin);
freopen("sgu282.out", "w", stdout);
#endif
cin >> n >> m >> Mod;
inv[0] = 1;
for(int i = 1; i <= n; ++i)
{
inv[i] = (LL)inv[i-1]*Inv(i, Mod)%Mod;
invl[i] = Inv(i, Mod);
}
mi[0] = 1;
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= n; ++j)
Gcd[i][j] = gcd(i, j), mi[(i-1)*n+j] = (LL)mi[(i-1)*n+j-1]*m%Mod;
L[0] = 1;
Dfs(1, 0);
cout << ans << endl;
#ifndef ONLINE_JUDGE
fclose(stdin);
fclose(stdout);
#endif
return 0;
}