bzoj1002/luogu2144 轮状病毒 (dp)
给周围的点编号1到n
我们设f[i]为(1到i和中间点)连成一个联通块的情况数,那么有$f[i]=\sum{f[i-j]*j}$,就是从i-j+1到i里选一个连到中心,然后再把i-j+1到i连成链
但这样的话,1和n不能连,那就再考虑,如果我们通过1-n这条边链起了i个点,那就再从这i个里连1个到中心点,剩下的点连成一个联通块。
这种情况设成g的话,就有$g=\sum{(j-1)*j*f[i-j]}$,其中(j-1)的意思是经过1-n、长度为j的有j-1种情况
然后要写高精度
1 #include<bits/stdc++.h> 2 #define pa pair<int,int> 3 #define ll long long 4 using namespace std; 5 const int maxn=110,maxs=220; 6 7 ll rd(){ 8 ll x=0;char c=getchar();int neg=1; 9 while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();} 10 while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar(); 11 return x*neg; 12 } 13 14 int N; 15 int f[maxn][maxs],g[maxs],tmp[maxs]; 16 17 inline void print(int *x){ 18 for(int i=x[0];i;i--) printf("%d",x[i]);printf("\n"); 19 } 20 21 inline void mult(int x,int k){ 22 memset(tmp,0,sizeof(tmp));int i; 23 for(i=1;i<=f[x][0];i++){ 24 tmp[i]+=f[x][i]*k; 25 tmp[i+1]+=tmp[i]/10;tmp[i]%=10; 26 }for(;;i++){if(!tmp[i]){tmp[0]=i-1;break;} 27 tmp[i+1]+=tmp[i]/10;tmp[i]%=10; 28 } 29 } 30 inline void add(int x){int i; 31 for(i=1;i<=tmp[0];i++){ 32 f[x][i]+=tmp[i]; 33 f[x][i+1]+=f[x][i]/10;f[x][i]%=10; 34 }for(;;i++){ 35 if(!f[x][i]){f[x][0]=max(f[x][0],i-1);break;} 36 f[x][i+1]+=f[x][i]/10;f[x][i]%=10; 37 } 38 } 39 40 int main(){ 41 int i,j,k; 42 N=rd();f[0][0]=f[0][1]=1; 43 for(i=1;i<=N;i++){ 44 for(j=1;j<=i;j++){ 45 mult(i-j,j);add(i); 46 } 47 } 48 for(i=1;i<=N;i++){ 49 mult(N-i,(i-1)*i);add(N+1); 50 }memcpy(tmp,f[N+1],sizeof(tmp));add(N); 51 print(f[N]); 52 return 0; 53 }