【AGC040C】Neither AB nor BA
题目
题目链接:https://atcoder.jp/contests/agc040/tasks/agc040_c
给定一个 \(n\),求有多少个长度为 \(n\) 且只包含 ABC
的字符串满足以下条件:
- 每次可以选定一个长度为 \(2\) 的子串删掉,且这个子串不为
AB
或BA
,直到整个字符串被删除。
\(n\leq 10^7\) 且 \(n\) 是偶数。
思路
对于一个合法的字符串 \(s\),把它偶数位置上的字符 AB
全部取反,这样原问题等价于在新串上每次删除长度为 \(2\) 的子串且不为 AA
或 BB
。因为每一个合法字符串之间都是一一对应的。
那么新问题只需要满足这个字符串 A
和 B
的出现次数不超过严格一半即可。容斥一下直接随便计数就好了。
时间复杂度 \(O(n)\)。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=10000010,MOD=998244353;
int n;
ll ans,fac[N],inv[N];
ll fpow(ll x,ll k)
{
ll ans=1;
for (;k;k>>=1,x=x*x%MOD)
if (k&1) ans=ans*x%MOD;
return ans;
}
ll C(int n,int m)
{
return fac[n]*inv[m]%MOD*inv[n-m]%MOD;
}
int main()
{
scanf("%d",&n);
fac[0]=inv[0]=1;
for (int i=1;i<=n;i++) fac[i]=fac[i-1]*i%MOD;
inv[n]=fpow(fac[n],MOD-2);
for (int i=n-1;i>=1;i--) inv[i]=inv[i+1]*(i+1)%MOD;
ans=fpow(3,n);
for (int i=n/2+1;i<=n;i++)
ans=(ans-2LL*C(n,i)*fpow(2,n-i))%MOD;
cout<<(ans%MOD+MOD)%MOD;
return 0;
}