サブ
問題の意味:長さ\(N- \) 、\(m個\)文字列\(S \) 、\(T \)、9桁0のストリングは、小数の組成物は、感を尋ね\(S \)より\(T \)数字列より大きな配列。
\(M \の当量のn \の当量 { 3000} \) 。
溶液を2つの異なるケースを考慮する:サブシーケンスの長さが等しい(T \)\より大きい配列および配列長さ\(T \)文字列。で\(LEN [I] [J ] \) メンテナンス\(S \)の文字列\(Iは\)前のビット長\(J \)法的列番号(先頭のゼロなし)、その後長さよりも大きい\ (T \)数値列である(\ \ sum_ = {I}。1 + M} ^ {N-LEN [N-] [I])\。
\(DP1 [I] [J ] \) メンテナンス\(S \)の文字列\(Iは\)長前にビット\(J \)よりも厳密に大きい\(T \)の前に文字列\(J \ )サブビットシーケンス番号、\(DP2である[I] [J] \)メンテナンス\(S \)の文字列\(Iは\)ビット長の前に\(J \)及び以上(T \)\文字列の前に\(J \)副ビットシーケンス番号は、それによって容易である\(S [I] \)と\(T [J] \)伝達方程式の一連の大小関係を導出しました。このように等しい長さ(T \)\数字列である(DP1 [N-] [m]を\)\。
コード:
#include <bits/stdc++.h>
using namespace std;
const int mod = 998244353;
char a[3005], b[3005];
int n, m;
int dp1[3005][3005], len[3005][3005], dp2[3005][3005];
int main() {
int T;
cin >> T;
while(T--) {
scanf("%d%d", &n, &m);
int ans1 = 0, ans2 = 0;
int maxx = max(n, m);
for(int i = 0; i <= maxx + 2; i++) for(int j = 0; j <= maxx + 2; j++) dp1[i][j] = dp2[i][j] = 0, len[i][j] = 0;
scanf("%s%s", a + 1, b + 1);
dp1[0][0] = 0;
dp2[0][0] = 1;
len[0][0] = 1;
for(int i = 1; i <= n; i++) {
len[i][0] = 1;
for(int j = 1; j <= i; j++) len[i][j] = (len[i - 1][j - 1] + len[i - 1][j]) % mod;
if(a[i] == '0') len[i][1] = len[i - 1][1];
dp2[i][0] = 1;
for(int j = 1; j <= i; j++) {
dp1[i][j] = dp1[i - 1][j];
dp2[i][j] = dp2[i - 1][j];
if(a[i] <= b[j]) {
dp1[i][j] = (dp1[i][j] + dp1[i - 1][j - 1]) % mod;
if(a[i] == b[j]) dp2[i][j] = (dp2[i][j] + dp2[i - 1][j - 1]) % mod;
else dp2[i][j] = (dp2[i][j] + dp1[i - 1][j - 1]) % mod;
}
if(a[i] > b[j]) {
dp1[i][j] = (dp1[i][j] + dp2[i - 1][j - 1]) % mod;
dp2[i][j] = (dp2[i][j] + dp2[i - 1][j - 1]) % mod;
}
//dp2[i][j] += dp1[i - 1][j - 1];
}
}
for(int i = m + 1; i <= n; i++) ans1 = (ans1 + len[n][i]) % mod;
ans2 = dp1[n][m];
int ans = (ans1 + ans2) % mod;
printf("%d\n", ans);
}
return 0;
}