CF2242D Two Digit Strings
唐题,但是忘了 \(LCS\) 所以没写出来……
注意到题目可以转化成找 \(x\) 个断点,把数组分成 \(x\) 段,每段求和取模,使最终 \(a = b\),求最大的 \(x\)。
根据余数加法的运算性质,每段和的模相同等价于断点前缀和的模相同。
因此我们先对两个数组分别求前缀和,然后求 \(LCS\) 就做完了。
\(-1\) 的条件是 \(\sum_{i = 1}^{n}a_i \equiv \sum_{i = 1}^{m}b_i \pmod{10}\) 不成立。
#include<bits/stdc++.h>
#define F(i,l,r) for(int i(l); i <= (r); ++ i)
#define G(i,r,l) for(int i(r); i >= (l); -- i)
using namespace std;
using ll = long long;
const int N = 1e4;
int n, m, T;
int f[N][N], s[N], t[N];
char a[N], b[N];
void Main(){
cin >> a >> b;
n = strlen(a);
m = strlen(b);
F(i, 0, n - 1){
s[i + 1] = (s[i] + a[i] - '0') % 10;
// printf("%d ", s[i + 1]);
}
// printf("\n");
F(i, 0, m - 1){
t[i + 1] = (t[i] + b[i] - '0') % 10;
// printf("%d ", t[i + 1]);
}
// printf("\n");
if(s[n] != t[m]){
cout << -1 << '\n';
return ;
}
F(i, 1, n){
F(j, 1, m){
f[i][j] = max(f[i][j - 1], f[i - 1][j]);
if(s[i] == t[j]) f[i][j] = max(f[i][j], f[i - 1][j - 1] + 1);
}
}
cout << f[n][m] << '\n';
f[0][0] = f[1][0] = f[0][1] = f[1][1] = 0;
return ;
}
signed main(){
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
cin >> T;
while(T --) Main();
return fflush(0), 0;
}

浙公网安备 33010602011771号