题目大意:求nnn个点的无向简单连通图边数平方的和,n≤2000n\le2000n≤2000。
题解:
考虑dp,设h0(n),h1(n),h2(n)h_0(n),h_1(n),h_2(n)h0(n),h1(n),h2(n)分别表示所有nnn个点无向简单图的边数的000次,111次,222次方和,记m=(n2)m=\binom n2m=(2n),易知:
h0(n)=2mh1(n)=m2m−1,h2(n)=∑i=1mi2(mi)=m(m+1)2m−2h_0(n)=2^m\\h_1(n)=m2^{m-1},\\h_2(n)=\sum_{i=1}^{m}i^2\binom mi=m(m+1)2^{m-2}h0(n)=2mh1(n)=m2m−1,h2(n)=i=1∑mi2(im)=m(m+1)2m−2
最后一个可以考虑对某个函数F(x)=(1+x)mF(x)=(1+x)^mF(x)=(1+x)m求导乘以x,再求导然后乘以x,然后令x=1即可;事实上可以推广到hk(n)h_k(n)hk(n)的情况。
令f0(n),f1(n),f2(n)f_0(n),f_1(n),f_2(n)f0(n),f1(n),f2(n)表示nnn个点无向简单连通图的边数的000次,111次,222次方和,则:
fk(n)=hk(n)−∑i=1n−1(n−1i−1)∑j=0k(kj)fjhk−jf_k(n)=h_k(n)-\sum_{i=1}^{n-1}\binom {n-1}{i-1}\sum_{j=0}^k\binom kj f_jh_{k-j}fk(n)=hk(n)−i=1∑n−1(i−1n−1)j=0∑k(jk)fjhk−j
这个也可以推广到fk(n)f_k(n)fk(n)的情况。
复杂度O(n2)O(n^2)O(n2)。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define N 2010
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define lint long long
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
int c[N][N],m[N],f0[N],f1[N],f2[N],h0[N],h1[N],h2[N],mod;
inline int fast_pow(int x,int k,int ans=1) { for(;k;k>>=1,x=(lint)x*x%mod) (k&1)?ans=(lint)ans*x%mod:0;return ans; }
int main()
{
int n;scanf("%d%d",&n,&mod);rep(i,1,n) m[i]=i*(i-1)/2;
rep(i,1,n) h0[i]=fast_pow(2,m[i]),(i>1?h1[i]=(lint)m[i]*fast_pow(2,m[i]-1)%mod:0),
(i>2?h2[i]=m[i]*(m[i]+1ll)%mod*fast_pow(2,m[i]-2)%mod:0);
h1[1]=0,h2[1]=0,h2[2]=1,f0[1]=1,f1[1]=0,f2[1]=0;rep(i,0,n) c[i][0]=1;
rep(i,1,n) rep(j,1,i) c[i][j]=c[i-1][j]+c[i-1][j-1],(c[i][j]>=mod?c[i][j]-=mod:0);
rep(i,2,n)
{
lint w0=0,w1=0,w2=0;
rep(j,1,i-1) w0+=(lint)c[i-1][j-1]*f0[j]%mod*h0[i-j]%mod,
w1+=((lint)f1[j]*h0[i-j]+(lint)f0[j]*h1[i-j])%mod*c[i-1][j-1]%mod,
w2+=((lint)f2[j]*h0[i-j]+2ll*f1[j]*h1[i-j]+(lint)f0[j]*h2[i-j])%mod*c[i-1][j-1]%mod;
f0[i]=h0[i]-(int)(w0%mod),(f0[i]<0?f0[i]+=mod:0),
f1[i]=h1[i]-(int)(w1%mod),(f1[i]<0?f1[i]+=mod:0),
f2[i]=h2[i]-(int)(w2%mod),(f2[i]<0?f2[i]+=mod:0);
}
return !printf("%d\n",f2[n]);
}