bzoj 1488: [HNOI2009]图的同构【polya定理+dfs】

把连边和不连边看成黑白染色,然后就变成了 https://www.cnblogs.com/lokiii/p/10055629.html
这篇讲得好!https://blog.csdn.net/wzq_qwq/article/details/48035455

#include<iostream>
#include<cstdio>
using namespace std;
const int N=65,mod=997;
int n,m=2,fac[N],ans,a[N];
int gcd(int a,int b)
{
	return !b?a:gcd(b,a%b);
}
int ksm(int a,int b)
{
	int r=1;
	while(b)
	{
		if(b&1)
			r=r*a%mod;
		a=a*a%mod;
		b>>=1;
	}
	return r;
}
void dfs(int w,int s,int y)
{
	if(!y)
	{
		int c=0,tot=1;
		int nw=1;
		for(int i=1;i<w;i++)
			c+=a[i]/2;
		for(int i=1;i<w;i++)
			for(int j=i+1;j<w;j++)
				c+=gcd(a[i],a[j]);
		for(int i=1;i<w;i++)
			nw=nw*a[i]%mod;
		for(int i=2;i<w;i++)
		{
			if(a[i]!=a[i-1])
				nw=nw*fac[tot]%mod,tot=0;
			tot++;
		}
		nw=fac[n]*ksm(nw*fac[tot]%mod,mod-2)%mod;
		ans=(ans+nw*ksm(m,c))%mod;
	}
	if(y<s)
		return;
	for(int i=s;i<=y;i++)
	{
		a[w]=i;
		dfs(w+1,i,y-i);
	}
}
int main()
{
	scanf("%d",&n);
	fac[0]=1;
	for(int i=1;i<=n;i++)
		fac[i]=fac[i-1]*i%mod;
	dfs(1,1,n);
	printf("%d\n",ans*ksm(fac[n],mod-2)%mod);
	return 0;
}
posted @ 2018-12-03 09:48  lokiii  阅读(231)  评论(0编辑  收藏  举报