求两两互不同构的含n个点的简单图有多少种。
简单图是关联一对顶点的无向边不多于一条的不含自环的图。
a图与b图被认为是同构的是指a图的顶点经过一定的重新标号以后,a图的顶点集和边集能完全与b图一一对应。
求两两互不同构的含n个点的简单图有多少种。
简单图是关联一对顶点的无向边不多于一条的不含自环的图。
输入一行一个整数N,表示图的顶点数,0<=N<=60
输出一行一个整数表示含N个点的图在同构意义下互不同构的图的数目,答案对997取模。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int ha=997,mod=ha-1;
inline int add(int x,int y){ x+=y; return x>=ha?x-ha:x;}
inline void ADD(int &x,int y){ x+=y; if(x>=ha) x-=ha;}
inline int ksm(int x,int y){
int an=1;
for(;y;y>>=1,x=x*(ll)x%ha) if(y&1) an=an*(ll)x%ha;
return an;
}
int gcd[73][73],n,ci[1005],ans,jc[73],ni[73];
int m,a[65],tot,now,C[73][73],b[65];
inline void calc(){
m=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=b[i];j++) a[++m]=i;
tot=0,now=1;
for(int i=1;i<=m;i++) tot+=a[i]>>1;
for(int i=1;i<=m;i++)
for(int j=i+1;j<=m;j++) tot+=gcd[a[i]][a[j]];
if(tot>=mod) tot%=mod;
for(int T=n,i=1;i<=m;T-=a[i],i++) now=now*(ll)C[T][a[i]]%ha*(ll)jc[a[i]-1]%ha;
for(int i=1;i<=n;i++) if(b[i]>1) now=now*(ll)ni[b[i]]%ha;
ADD(ans,now*(ll)ci[tot]%ha);
}
void dfs(int x,int lef){
if(lef<x){ if(!lef) calc(); return;}
for(int i=0,u=0;u<=lef;i++,u+=x) b[x]=i,dfs(x+1,lef-u),b[x]=0;
}
int main(){
ci[0]=1; for(int i=1;i<ha;i++) ci[i]=add(ci[i-1],ci[i-1]);
jc[0]=1; for(int i=1;i<=60;i++) jc[i]=jc[i-1]*(ll)i%ha;
ni[60]=ksm(jc[60],ha-2);
for(int i=60;i;i--) ni[i-1]=ni[i]*(ll)i%ha;
C[0][0]=1;
for(int i=1;i<=60;i++){
C[i][0]=1;
for(int j=1;j<=i;j++) C[i][j]=add(C[i-1][j-1],C[i-1][j]);
}
scanf("%d",&n);
for(int i=0;i<=n;i++)
for(int j=0;j<=i;j++)
if(!i||!j) gcd[i][j]=i+j;
else gcd[j][i]=gcd[i][j]=gcd[j][i%j];
dfs(1,n),ans=ans*(ll)ni[n]%ha;
printf("%d\n",ans);
return 0;
}
原文:https://www.cnblogs.com/JYYHH/p/9245045.html