1.トピックリンク
\ quad パイプビーズ抽出
2.トピックの主なアイデア
\ quad 元の質問は素晴らしいです。
3.分析
\ quad この質問は素晴らしい片手変換です、私はそれを学びました~~
\ quad この問題では、a [i]を最終シーケンスの特定の数の解としますが、[i] 2 a [i] ^ 2を解きます。a [ i ]2.明らかに、2つの関係を見つける必要があります。
\ quad 2つの同一の独立したシステムがあり、2人が同時に操作していると仮定すると、特定の最終シーケンスFについて、操作後に2人が取得した解の数がFと同じであることを証明することは難しくありません[i] 2 a [i] ^ 2a [ i ]2
\ quad この変換ステップの後、dpをスパイシーにすることができます~~(しかしガチョウはそうではありません...)
\ quad dp [i] [j] [k] [l]を、パイプ1からiボールを取得する最初の人、パイプ2からjボールを取得する最初の人、パイプ1からjボールを取得する2番目の人とします。 k個のボール、2人目はパイプ2からl個のボールを取り出し、現在同じシーケンスのスキームの数が構成されています。
\ quad しかし、そのような状態は時間と空間が破裂することを意味します.2つのシーケンスが同じであるため、i + j == k + lであるため、最初の次元でのローリング最適化に加えて、1つの次元を省略できます。 ACの時間と空間を入力してください!
\ quad 状態遷移方程式は
if(s[i + 1] == s[k + 1]) f[p^1][j][k + 1] = (f[p^1][j][k + 1] + f[p][j][k]) % mod;
if(s[i + 1] == t[l + 1]) f[p^1][j][k] = (f[p^1][j][k] + f[p][j][k]) % mod;
if(t[j + 1] == s[k + 1]) f[p][j + 1][k + 1] = (f[p][j + 1][k + 1] + f[p][j][k]) % mod;
if(t[j + 1] == t[l + 1]) f[p][j + 1][k] = (f[p][j + 1][k] + f[p][j][k]) % mod;
さらに、以下のサンプルペーパーのように、少し最適化を追加できます
if(!f[p][j][k]) continue;
if(s[i + 1] == s[k + 1]) f[p^1][j][k + 1] = (f[p^1][j][k + 1] + f[p][j][k]) % mod;
if(s[i + 1] == t[l + 1]) f[p^1][j][k] = (f[p^1][j][k] + f[p][j][k]) % mod;
if(t[j + 1] == s[k + 1]) f[p][j + 1][k + 1] = (f[p][j + 1][k + 1] + f[p][j][k]) % mod;
if(t[j + 1] == t[l + 1]) f[p][j + 1][k] = (f[p][j + 1][k] + f[p][j][k]) % mod;
\ quad テスト後、制限時間は大幅に最適化されました。!!
4.コードの実装
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int M = (int)5e2;
const ll mod = (ll)1024523;
const int inf = 0x3f3f3f3f;
const double eps = 1e-8;
int n, m;
char s[M + 5], t[M + 5];
int f[2][M + 5][M + 5];
int main()
{
// freopen("input.txt", "r", stdin);
// freopen("output.txt", "w", stdout);
scanf("%d %d", &n, &m);
scanf("%s %s", s + 1, t + 1);
reverse(s + 1, s + n + 1); reverse(t + 1, t + m + 1);
f[0][0][0] = 1;
for(int i = 0, p = 0; i <= n; ++i, p ^= 1)
{
for(int j = 0; j <= m; ++j)
{
for(int k = 0; k <= n; ++k)
{
int l = i + j - k;
if(l < 0 || l > m) continue;
if(!f[p][j][k]) continue;
if(s[i + 1] == s[k + 1]) f[p^1][j][k + 1] = (f[p^1][j][k + 1] + f[p][j][k]) % mod;
if(s[i + 1] == t[l + 1]) f[p^1][j][k] = (f[p^1][j][k] + f[p][j][k]) % mod;
if(t[j + 1] == s[k + 1]) f[p][j + 1][k + 1] = (f[p][j + 1][k + 1] + f[p][j][k]) % mod;
if(t[j + 1] == t[l + 1]) f[p][j + 1][k] = (f[p][j + 1][k] + f[p][j][k]) % mod;
f[p][j][k] = 0;
}
}
}
printf("%d\n", f[(n + 1) & 1][m][n]);
return 0;
}