[NOI2009]管道区珠

时间:2019-09-22
本文章向大家介绍[NOI2009]管道区珠,主要包括[NOI2009]管道区珠使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

[NOI2009]管道取珠
对于\(\sum a[i]^2\)
我们不如把它理解成
一个取珠游戏A和一个取珠游戏B同时举行,当A中的任意一个结果和B中的任意一个结果相同时,我们把它加进方案
f[i][j]表示A游戏中上管道取了i个球,B游戏中上管道取了j个球(一个循环枚举k,所以A游戏中下管道取了k-i个球,B游戏中下管道取了k-j个球)
于是便非常的简单了
代码

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
#define MAXN 610
#define MOD 1024523
int n, m;
int a[MAXN], b[MAXN], f[MAXN][MAXN], c[MAXN][MAXN];
inline int read() {
    int s = 0, w = 1;
    char c = getchar();
    for (; !isdigit(c); c = getchar()) if (c == '-') w = -1;
    for (; isdigit(c); c = getchar()) s = (s << 1) + (s << 3) + (c ^ 48);
    return s * w;
}
int main() {
    n = read(), m = read();
    for (register int i = 1; i <= n; i++)
        a[n + 1 - i] = getchar() - 'A';
    getchar();
    for (register int i = 1; i <= m; i++)
        b[m + 1 - i] = getchar() - 'A';
    f[0][0] = 1;
    for (register int k = 1; k <= n + m; k++) {
        for (register int i = max(0, k - m); i <= min(k, n); i++)
            for (register int j = max(0, k - m); j <= min(k, n); j++) {
                c[i][j] = 0;
                if (a[i] == a[j] && i && j)
                    (c[i][j] += f[i - 1][j - 1]) %= MOD;
                if (a[i] == b[k - j] && i)
                    (c[i][j] += f[i - 1][j]) %= MOD;
                if (b[k - i] == a[j] && j)
                    (c[i][j] += f[i][j - 1]) %= MOD;
                if (b[k - i] == b[k - j])
                    (c[i][j] += f[i][j]) %= MOD;
            }
        for (register int i = 0; i <= min(k, n); i++)
            for (register int j = 0; j <= min(k, n); j++)
                f[i][j] = c[i][j];
    }
    printf("%d", f[n][n]);
    return 0;
}

原文地址:https://www.cnblogs.com/Agakiss/p/11568927.html