【AGC040C】Neither AB nor BA

题目

题目链接:https://atcoder.jp/contests/agc040/tasks/agc040_c
给定一个 \(n\),求有多少个长度为 \(n\) 且只包含 ABC 的字符串满足以下条件:

  • 每次可以选定一个长度为 \(2\) 的子串删掉,且这个子串不为 ABBA,直到整个字符串被删除。

\(n\leq 10^7\)\(n\) 是偶数。

思路

对于一个合法的字符串 \(s\),把它偶数位置上的字符 AB 全部取反,这样原问题等价于在新串上每次删除长度为 \(2\) 的子串且不为 AABB。因为每一个合法字符串之间都是一一对应的。
那么新问题只需要满足这个字符串 AB 的出现次数不超过严格一半即可。容斥一下直接随便计数就好了。
时间复杂度 \(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;
}
posted @ 2021-07-15 11:31  stoorz  阅读(44)  评论(0编辑  收藏  举报