题目链接
https://www.lydsy.com/JudgeOnline/problem.php?id=5346
思路
这道题要求对取膜……
用表示选取个点,这个点的度数为的方案数,直接在prufer序列上dp就可以了。时间复杂度。
代码
#include <cstdio>
#include <algorithm>
const int maxn=100;
const int mo=1004535809;
int read()
{
int x=0,f=1;
char ch=getchar();
while((ch<'0')||(ch>'9'))
{
if(ch=='-')
{
f=-f;
}
ch=getchar();
}
while((ch>='0')&&(ch<='9'))
{
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
int fac[maxn+10],ifac[maxn+10];
int n,d[maxn+10],f[maxn+10][maxn*2+10];
int quickpow(int a,int b,int m)
{
int res=1;
while(b)
{
if(b&1)
{
res=1ll*res*a%m;
}
a=1ll*a*a%m;
b>>=1;
}
return res;
}
int main()
{
n=read();
for(int i=1; i<=n; ++i)
{
d[i]=std::min(read(),n-1);
}
fac[0]=1;
for(int i=1; i<=n; ++i)
{
fac[i]=1ll*fac[i-1]*i%mo;
}
ifac[n]=quickpow(fac[n],mo-2,mo);
for(int i=n-1; i>=0; --i)
{
ifac[i]=1ll*ifac[i+1]*(i+1)%mo;
}
f[0][0]=1;
for(int u=1; u<=n; ++u)
{
for(int i=u-1; i>=0; --i)
{
for(int j=n*2-2; j>=0; --j)
{
if(f[i][j])
{
for(int k=std::min(n*2-2-j,d[u]); k; --k)
{
f[i+1][j+k]=(f[i+1][j+k]+1ll*f[i][j]*ifac[k-1]%mo)%mo;
}
}
}
}
}
printf("%d ",n);
for(int i=2; i<n; ++i)
{
printf("%d ",1ll*f[i][i*2-2]*fac[i-2]%mo);
}
if(n!=1)
{
printf("%d\n",1ll*f[n][n*2-2]*fac[n-2]%mo);
}
return 0;
}