一個長度爲 n 的字符串是好的當且僅當它由 'A', 'B', 'C' 組成,且能夠經過若干次刪除除了"AB"和"BA"的連續子串變爲空串。ios
問有多少個長度爲 n 的好串,對 998244353 取模。git
\(n\le 10 ^ 7\) , 保證 n 爲偶數。spa
本題的關鍵在於轉化題意,即找到一個更加簡潔抽象的等價條件方便計數。code
連續刪除兩個字符後發現每個 A 和 B 的奇偶性沒有改變。ip
這說明了奇數位置的 A 必定不能和偶數位置的 B 消除,偶數位置的 A 不能和奇數位置的B消除。ci
設奇數位置的 A 有 x 個,偶數位置的 B 有 y 個,偶數位置的非 B 字符有 n - y 個, 那麼必須知足(即必要性):字符串
\[ x \le \frac{n}{2} - y\\ x + y \le \frac n2 \]get
因此有:input
奇數位置上A的數量 + 偶數位置上B的數量\(\le \frac n 2\)string
奇數位置上B的數量 + 偶數位置上A的數量\(\le \frac n 2\)
必要性顯然。
仿照上式子記爲:
\[ c + d \le \frac n 2 \\ a + b \le \frac n 2 \]
充分性能夠考慮先吧序列的 C 都消掉,剩只需考慮 A 和 B 。
因爲
\(a + c = b + d = \frac n 2\)
因此
\(a + d = b + c = \frac n 2\)
這樣就必然能夠找到一對 AA 或 BB 消去。
Thus,\(Ans = 3 ^ n - count(a + b > \frac n 2) - count(c + d > \frac n 2)\) 。
枚舉有多少個 a + b (c + d) ,其他的位置就只有兩種方案,用組合數算一下便可.
#include <cstdio> #include <cstring> #include <vector> #include <iostream> #include <algorithm> using namespace std; #define End exit(0) #define LL long long #define mp make_pair #define SZ(x) ((int) x.size()) #define GO cerr << "GO" << endl #define DE(x) cout << #x << " = " << x << endl #define DEBUG(...) fprintf(stderr, __VA_ARGS__) void proc_status() { freopen("/proc/self/status","r",stdin); string s; while(getline(cin, s)) if (s[2] == 'P') { cerr << s << endl; return; } } template<typename T> inline T read() { register T x = 0; register char c; register int f(1); while (!isdigit(c = getchar())) if (c == '-') f = -1; while (x = (x << 1) + (x << 3) + (c ^ 48), isdigit(c = getchar())); return x * f; } template<typename T> inline bool chkmin(T &a,T b) { return a > b ? a = b, 1 : 0; } template<typename T> inline bool chkmax(T &a,T b) { return a < b ? a = b, 1 : 0; } const int maxN = 1e7 + 2; const int mod = 998244353; int qpow(int a, int b) { int ans = 1; for (; b; b >>= 1, a = 1ll * a * a % mod) if (b & 1) ans = 1ll * ans * a % mod; return ans; } inline void Inc(int &x) { x < 0 ? x += mod : 0; } int fac[maxN + 2], ifac[maxN + 2], pw2[maxN + 2]; void init(int N = 1e7) { fac[0] = 1; for (int i = 1; i <= N; ++i) fac[i] = (LL) fac[i - 1] * i % mod; ifac[N] = qpow(fac[N], mod - 2); for (int i = N - 1; i >= 0; --i) ifac[i] = (LL) ifac[i + 1] * (i + 1) % mod; pw2[0] = 1; for (int i = 1; i <= N; ++i) pw2[i] = pw2[i - 1] * 2ll % mod; } int C(int n, int m) { if (n < m) return 0; return (LL) fac[n] * ifac[m] % mod * ifac[n - m] % mod; } int n; void input() { n = read<int>(); } void solve() { int ans = qpow(3, n); for (int i = n / 2 + 1; i <= n; ++i) Inc(ans -= 2ll * C(n, i) * pw2[n - i] % mod); printf("%d\n", ans); } int main() { #ifndef ONLINE_JUDGE freopen("xhc.in", "r", stdin); freopen("xhc.out", "w", stdout); #endif input(), init(), solve(); return 0; }