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

【題解】NOI2009管道取珠

clas bits 之間 滾動 有著 color while 堅持 平方和

  又是艱難想題的一晚,又是做不出來的一題 (;д;) 好想哭啊……

  這題最關鍵的一點還是提供一種全新的想法。看到平方和這種東西,真的不好dp。然而我一直陷在化式子的泥潭中出不來。平方能夠聯想到什麽?原本的方案的乘積。將兩部分相乘,我們能夠聯想到這是兩個人在取珠,求他們取出來的珠子顏色序列相同的方案數之和。(第一個人要得到 \(x\) 這種顏色方案有\(a_{x}\)種,第二個人也一樣。所以一共為 \({a_{x}}^{2}\) 種。到這裏,應該就很容易了。雖然看了題解之後恍然大悟,然而深深地明白目前的自己與做出此題之間仍然是有著無法逾越的鴻溝的。唯有堅持努力下去,勤加積累才能夠等到柳暗花明的一天 (≧?≦)?

  註意滾動數組哦。

#include <bits/stdc++.h>
using namespace std;
#define maxn 505
#define mod 1024523
int n, m, a[maxn], b[maxn];
int pre = 0, now = 1, f[2][maxn][maxn];
char c;

int read()
{
    int x = 0, k = 1;
    char c;
    c = getchar();
    while(c < 0 || c > 9) { if(c == -) k = -1; c = getchar(); }
    
while(c >= 0 && c <= 9) x = x * 10 + c - 0, c = getchar(); return x * k; } void up(int &x, int y) { x = (x + y) % mod; } int main() { int n = read(), m = read(); for(int i = 1; i <= n; i ++) { cin >> c; if(c == B) a[n - i + 1] = 1; }
for(int i = 1; i <= m; i ++) { cin >> c; if(c == B) b[m - i + 1] = 1; } f[0][0][0] = 1; for(int i = 1; i <= n + m; i ++) { int lim1 = min(i, n), lim2 = min(i, n); for(int j = 0; j <= lim1; j ++) for(int k = 0; k <= lim2; k ++) { f[now][j][k] = 0; int x = i - j, y = i - k; if(x > m || y > m) continue; if(a[j] == a[k]) up(f[now][j][k], f[pre][j - 1][k - 1]); if(a[j] == b[i - k]) up(f[now][j][k], f[pre][j - 1][k]); if(b[i - j] == a[k]) up(f[now][j][k], f[pre][j][k - 1]); if(b[i - j] == b[i - k]) up(f[now][j][k], f[pre][j][k]); } swap(pre, now); } printf("%d\n", f[pre][n][n]); return 0; }

【題解】NOI2009管道取珠