1. 程式人生 > >BZOJ1566 【NOI2009】管道取珠

BZOJ1566 【NOI2009】管道取珠

時也 stdin 神題 cto long long vector can open gist

題面

這是一道DP神題,直到我寫下這句題解時也沒有想明白……

首先,這道題要我們求所有(不同輸出序列的方案數)的平方和,於是我們當然就想到求所有不同輸出序列的方案數……(大霧) 。這道題一個巧妙的地方就在於對問題的轉化。(以下摘自BYVoid大神的題解)

假設同時有兩個人X & Y在玩這個遊戲,Xup取了i個珠子(不一定連續),從down取了j個珠子,取出來的珠子組成的序列為Q操作序列為x,Yup取了k個珠子,從down取了l個珠子,取出來的珠子組成的序列也為Q,操作序列為y,那麽我們就得到了一個有序對(xy,f[i][j][k][l]即表示有序對(xy)的數量。兩個有序對不相同當且僅當x

y不同時相同

下面證明f[i][j][k][l]即為所求。

已知:取出珠子的序列為Qxy分別為一種取珠方法(可相同), 取出Q的方案數為a

求證:有序對(xy)的數量等於a2

因為取出Q的方案數為a,所以x & y都有a種取值,且x & y彼此獨立,故對於x的每一個取值,y都有a種取值,故有序對(xy)的數量為a2,命題得證。

博主是個超級大傻*,連空間優化到n2都不會,請各路大神指教。

 1 #include <map>
 2 #include <set>
 3 #include <cmath>
 4 #include <queue>
 5
#include <stack> 6 #include <cstdio> 7 #include <string> 8 #include <vector> 9 #include <cstring> 10 #include <complex> 11 #include <cstdlib> 12 #include <iostream> 13 #include <algorithm> 14 #define rg register 15 #define ll long long 16 using
namespace std; 17 18 inline int gi() 19 { 20 rg int r = 0; rg bool b = 1; rg char c = getchar(); 21 while (c < 0 || c > 9) { if (c == -) b = 0; c = getchar(); } 22 while (c >= 0 && c <= 9) { r = r * 10 + c - 0, c = getchar(); } 23 if (b) return r; return -r; 24 } 25 26 const int inf = 2147483647, N = 505, MOD = 1024523; 27 int n,m,f[N][N][N]; 28 char S[N],X[N]; 29 30 inline void input() 31 { 32 freopen ("!.in", "r", stdin); 33 n=gi(), m=gi(); 34 scanf("%s%s",S+1,X+1); 35 } 36 37 inline void output() 38 { 39 freopen ("!.out", "w", stdout); 40 printf("%d\n",f[n][m][n]); 41 } 42 43 inline void cal(int &t,int d) { t+=d; if (t >= MOD) t-=MOD; } 44 45 inline void solve() 46 { 47 int i,j,k,l,tmp; 48 f[0][0][0]=1; 49 for (i=0; i<=n; i++) 50 for (j=0; j<=m; j++) 51 for (k=0; k<=n; k++) 52 { 53 tmp=f[i][j][k], l=i+j-k; 54 if (!tmp || !l || l > m) continue; 55 if (S[i+1] == S[k+1]) 56 cal(f[i+1][j][k+1],tmp); 57 if (X[j+1] == S[k+1]) 58 cal(f[i][j+1][k+1],tmp); 59 if (S[i+1] == X[l+1]) 60 cal(f[i+1][j][k],tmp); 61 if (X[j+1] == X[l+1]) 62 cal(f[i][j+1][k],tmp); 63 } 64 } 65 66 int main() 67 { 68 input(); 69 solve(); 70 output(); 71 return 0; 72 }

BZOJ1566 【NOI2009】管道取珠