首页 > 代码库 > bzoj1566 [NOI2009]管道取珠

bzoj1566 [NOI2009]管道取珠

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1566

【题解】

考虑表示的实际意义,相当于我取两次球,得到方案完全相同的个数。

设$f_{i,j,k}$表示取了$i$个,第一种上面取$j$个,第二种上面取$k$个,随便转移。

复杂度$O(n^3)$。

技术分享
# include <stdio.h>
# include <string.h>
# include <iostream>
# include <algorithm>
// # include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
const int M = 5e2 + 10;
const int mod = 1024523;

int f[2][M][M];

int nA, nB;
char a[M], b[M];

inline void cadd(int &a, int b) {
    a += b;
    if(a >= mod) a -= mod;
}

int main() {
    cin >> nA >> nB;
    scanf("%s%s", a+1, b+1);
    reverse(a+1, a+nA+1);
    reverse(b+1, b+nB+1);
    int cur = 0, nxt = 1;
    f[cur][0][0] = 1;
    for (int i=0; i<nA+nB; ++i) {
        int end_num = min(nA, i);
        memset(f[nxt], 0, sizeof f[nxt]);
        for (int j=0, jj; j<=end_num; ++j)
            for (int k=0, kk; k<=end_num; ++k) 
                if(f[cur][j][k]) {
                    jj = i - j, kk = i - k;
                    if(jj > nB || kk > nB) continue;
                    if(a[j+1] == a[k+1]) cadd(f[nxt][j+1][k+1], f[cur][j][k]);
                    if(b[jj+1] == a[k+1]) cadd(f[nxt][j][k+1], f[cur][j][k]);
                    if(a[j+1] == b[kk+1]) cadd(f[nxt][j+1][k], f[cur][j][k]);
                    if(b[jj+1] == b[kk+1]) cadd(f[nxt][j][k], f[cur][j][k]);
                }
        swap(cur, nxt);
    }
    cout << f[cur][nA][nA];
    return 0;
}
View Code

 

bzoj1566 [NOI2009]管道取珠