1. 程式人生 > >BZOJ1002: [FJOI2007]輪狀病毒 (DP)

BZOJ1002: [FJOI2007]輪狀病毒 (DP)

font 代碼 img 技術 sin pen none algorithm else

標準做法似乎應該是計算生成樹數量的基爾霍夫矩陣之類的..

我看到的做法是一個神奇的高精度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

BZOJ1002: [FJOI2007]輪狀病毒 (DP)