简单题。
考虑到有个性质:
若我们已经知道串 、 长啥样,就可以用这样的方式计算最小交换次数:
- ,考虑令 等于 的长度为 的前缀中 的出现次数 减去 的长度为 的前缀中 的出现次数,则跨过这个位置的交换一定至少有 步。
- 将所有位置的最小交换次数加起来,则可得到将 变成 的最小交换次数。
注意到需要统计答案的部分只和前缀 的个数差有关,于是可以数位 :
考虑设 表示前 个位置,此时 、 两个串 的个数差值为 ,且:
- 、 均贴上界
- 仅有 贴上界
- 、 均未贴上界且已经比较出大小
- 、 均未贴上界且没有比较出大小
时,所有合法状态的最小交换次数和。再设辅助数组 表示如上状态的方案数。
然后直接大力讨论转移就行了。
/******************************************************************************** Code by a weak man who named CYJian, and he hopes the code can get more points. Algorithm: ********************************************************************************/ #include <bits/stdc++.h> using namespace std; typedef long long ll; typedef unsigned long long ull; //{{{ FAST IO AND SOME FUNCTIONS const int __SIZE = 1 << 18; char ibuf[__SIZE], *iS, *iT; #define ge (iS == iT ? (iT = (iS = ibuf) + fread(ibuf, 1, __SIZE, stdin), (iS == iT ? EOF : *iS++)) : *iS++) #define ri read_int() #define rl read_ll() #define FILE(s) freopen(s"in", "r", stdin), freopen(s"out", "w", stdout) template<typename T> inline void read(T &x) { char ch, t = 0; x = 0; while(!isdigit(ch = ge)) t |= ch == '-'; while(isdigit(ch)) x = x * 10 + (ch ^ 48), ch = ge; x = t ? -x : x; } inline int read_int() { int x; return read(x), x; } inline ll read_ll() { ll x; return read(x), x; } template<typename T> inline void chkmin(T&a, T b) { a = a < b ? a : b; } template<typename T> inline void chkmax(T&a, T b) { a = a > b ? a : b; } //}}} const int inf = 1e9; const int mod = 998244353; const int MAXN = 20010; inline int Mod(int x) { return x >= mod ? x - mod : x; } inline void Add(int &x, int y) { x += y, x -= x >= mod ? mod : 0; } inline int fsp(int x, int k = mod - 2) { int s = 1; while(k) { if(k & 1) s = 1LL * s * x % mod; x = 1LL * x * x % mod, k >>= 1; } return s; } inline int gcd(int x, int y) { return !y ? x : gcd(y, x % y); } int f[1010][2010][4]; int g[1010][2010][4]; char s[1010]; int main() { #ifdef LOCAL FILE("a."); #endif scanf("%s", s + 1); int n = strlen(s + 1), Ad = 1002; g[0][Ad][2] = 1; for(int i = 0; i < n; i++) { for(int j = -i; j <= i; j++) { int G0 = g[i][j + Ad][0]; int G1 = g[i][j + Ad][1]; int G2 = g[i][j + Ad][2]; int G3 = g[i][j + Ad][3]; int F0 = f[i][j + Ad][0]; int F1 = f[i][j + Ad][1]; int F2 = f[i][j + Ad][2]; int F3 = f[i][j + Ad][3]; /* cout << i << ' ' << j << ' ' << 0 << ' ' << G0 << ' ' << F0 << endl; cout << i << ' ' << j << ' ' << 1 << ' ' << G1 << ' ' << F1 << endl; cout << i << ' ' << j << ' ' << 2 << ' ' << G2 << ' ' << F2 << endl; cout << endl; */ Add(g[i + 1][j + Ad][0], Mod(G0 << 1)); Add(f[i + 1][j + Ad][0], 2LL * (F0 + 1LL * abs(j) * G0) % mod); Add(g[i + 1][j + Ad + 1][0], G0); Add(f[i + 1][j + Ad + 1][0], (F0 + 1LL * abs(j) * G0) % mod); Add(g[i + 1][j + Ad - 1][0], G0); Add(f[i + 1][j + Ad - 1][0], (F0 + 1LL * abs(j) * G0) % mod); Add(g[i + 1][j + Ad][3], Mod(G3 << 1)); Add(f[i + 1][j + Ad][3], 2LL * (F3 + 1LL * abs(j) * G3) % mod); Add(g[i + 1][j + Ad + 1][0], G3); Add(f[i + 1][j + Ad + 1][0], (F3 + 1LL * abs(j) * G3) % mod); if(s[i + 1] == '0') { Add(g[i + 1][j + Ad][2], G2); Add(f[i + 1][j + Ad][2], (F2 + 1LL * abs(j) * G2) % mod); Add(g[i + 1][j + Ad][1], G1); Add(f[i + 1][j + Ad][1], (F1 + 1LL * abs(j) * G1) % mod); Add(g[i + 1][j - 1 + Ad][1], G1); Add(f[i + 1][j - 1 + Ad][1], (F1 + 1LL * abs(j) * G1) % mod); } else { Add(g[i + 1][j + Ad][2], G2); Add(f[i + 1][j + Ad][2], (F2 + 1LL * abs(j) * G2) % mod); Add(g[i + 1][j + Ad + 1][1], G2); Add(f[i + 1][j + Ad + 1][1], (F2 + 1LL * abs(j) * G2) % mod); Add(g[i + 1][j + Ad][3], G2); Add(f[i + 1][j + Ad][3], (F2 + 1LL * abs(j) * G2) % mod); Add(g[i + 1][j + Ad][1], G1); Add(f[i + 1][j + Ad][1], (F1 + 1LL * abs(j) * G1) % mod); Add(g[i + 1][j + Ad + 1][1], G1); Add(f[i + 1][j + Ad + 1][1], (F1 + 1LL * abs(j) * G1) % mod); Add(g[i + 1][j + Ad - 1][0], G1); Add(f[i + 1][j + Ad - 1][0], (F1 + 1LL * abs(j) * G1) % mod); Add(g[i + 1][j + Ad][0], G1); Add(f[i + 1][j + Ad][0], (F1 + 1LL * abs(j) * G1) % mod); } } } cout << Mod(Mod(f[n][Ad][0] + f[n][Ad][1]) + f[n][Ad][2]) << endl; return 0; }