BZOJ1002: [FJOI2007]轮状病毒 (DP)

标准做法似乎应该是计算生成树数量的基尔霍夫矩阵之类的..

我看到的做法是一个神奇的高精度dp,当然以后这个blahblahblah矩阵还是要搞一下。。
 
 
这个dp的原理就是把环拆成一条含特定点的链和剩下部分(可用dp解决),这样就避免了环具有的一些dp不好解决的奇怪判定.
非常神奇
%想出这个办法的dalao
 
附上非常不走心的非常丑的自己的代码..
 
 1 #include<cmath>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<iostream>
 5 #include<algorithm>
 6 #include<queue>
 7 using namespace std;
 8 int n;
 9 int f[110][2][35]={};//1 到i的单独一段都和中间连上了 0 到i的单独一段没有和中间连上
10 int ans[35]={};
11 int z[35]={};
12 int a[35]={};
13 int b[35]={};
14 int w=0;
15 void plu(){//a+b存z
16     int e=0;
17     for(int i=1;i<=30;i++){
18         e=a[i]+b[i]+e;
19         z[i]=e%10000;
20         e/=10000;
21     }
22 }
23 void mul(){//b*w存z
24     int e=0;
25     for(int i=1;i<=30;i++){
26         e=w*b[i]+e;
27         z[i]=e%10000;
28         e/=10000;
29     }
30 }
31 int main(){
32     scanf("%d",&n);
33     f[1][1][1]=f[1][0][1]=1;
34     f[0][1][1]=1;
35     for(int i=2;i<=n;i++){
36         for(int j=1;j<=30;j++){
37             a[j]=f[i-1][0][j];
38             b[j]=f[i-1][1][j];
39         }
40         plu();
41         for(int j=1;j<=30;j++){
42             f[i][0][j]=z[j];
43             z[j]=0;
44         }
45         
46         w=2;
47         mul();
48         for(int j=1;j<=30;j++){
49             b[j]=z[j];
50             z[j]=0;
51         }
52         plu();
53         for(int j=1;j<=30;j++){
54             f[i][1][j]=z[j];
55             z[j]=0;
56         }
57     }
58     for(int i=1;i<=n;i++){
59         w=i*i;
60         for(int j=1;j<=30;j++){
61             b[j]=f[n-i][1][j];
62             a[j]=ans[j];
63         }
64         mul();
65         for(int j=1;j<=30;j++){
66             b[j]=z[j];
67             z[j]=0;
68         }
69         plu();
70         for(int j=1;j<=30;j++){
71             ans[j]=z[j];
72             z[j]=0;
73         }
74     }
75     int f=0;
76     for(int i=30;i>=1;i--){
77         if(ans[i]!=0&&f==0){
78             f=1;
79             printf("%d",ans[i]);
80             continue;
81         }
82         if(f){
83             if(ans[i]>999){
84                 cout<<ans[i];
85             }
86             else if(ans[i]>99){
87                 cout<<0<<ans[i];
88             }
89             else if(ans[i]>9){
90                 cout<<0<<0<<ans[i];
91             }
92             else{
93                 cout<<0<<0<<0<<ans[i];
94             }
95         }
96     }
97     cout<<endl;
98     return 0;
99 }
View Code

 

posted @ 2017-11-04 17:02  鲸头鹳  阅读(254)  评论(0编辑  收藏  举报