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 }

猜你喜欢

转载自www.cnblogs.com/Ressed/p/9634333.html