AT5661 [AGC040C] Neither AB nor BA:数论,组合数学

题目来源: AT5661 [AGC040C] Neither AB nor BA.
参考题解: Tea’s blog
LXD让我们做这个题目,当然先是手玩啦,找删的掉得太多,所以找删不掉得。n=2:AB BA ,n=4 前面补,后面补等等写了写式子,发现在删不掉得基础上补了,前面得又被删掉了,无头绪,抄题解啦。
题解很巧妙,处理AB的在奇偶位置上的个数关系。成功的将题目转为数学题!
我们可以发现,将一个字串的A替换为B,B替换为A,性质不变,因此可以只处理一半。
我们设奇数位置上的A有xx个,偶数位置上的B有yy个,则有
{x<=n2y<=n2 \begin{cases} x<=\frac {n}{2}\\ y<=\frac n2 \end{cases}
偶数位置上的非B符号,也就是A和C有n2y\frac n2-y个,每个非B都可以删掉一个奇数位置上的A,如果删完了有剩下的,那必然有奇数位置上的A和偶数位置上的B相邻,什么时候才能有剩下的?也即是x>=n2yx>=\frac n2-y;移向后得x+y>=n2x+y>=\frac n2.
因此我们找出所有情况减去删不掉的情况也即是:
3n2count((x+y)>n2)3^n-2*count((x+y)>\frac n2)

如何计算:count((x+y))count((x+y))

分为两部分:

  • 奇A偶B无关的数据
    x+y=tx+y=t,则奇A偶B无关的数据有ntn-t个,在奇数位置上可填的数据是B,C,在偶数位置上可以填的数据是A,C,各有两种情况,因此总数是2nt2^{n-t};
  • 奇A偶B数据
    也就是从n个数里选出t个数,其中奇数有xx个,偶数有yy个。
    开始我是这么想的
    例如:n=6,t=4n=6,t=4的情况:
    {x=1,y=3;C31C33x=2,y=2;C22C22x=3,y=1;C33C31\begin{cases}x=1,y=3;C^1_3*C^3_3 \\x=2,y=2;C^2_2*C^2_2\\x=3,y=1;C^3_3*C^1_3\end{cases}
    计算完了之后发现是3+3*3+3=15,正好是C64C^4_6,也就是我们只需要从nn中选出tt个数,也就是CntC^t_n。其中奇数的位置放上A,偶数的位置放上B,这样就符合要求了。
    因此删不完得字串个数就是: Cnt2ntC^t_n*2^{n-t}

如何计算:count((x+y)>n2)count((x+y)>\frac n2)

t=n2+1nCnt2nt\sum_{t=\frac n2+1}^{n}*C^t_n*2^{n-t}

到这里我自己就理清思路了。顺便复习了下markdown,但我过会又会忘记的——已经18岁的老年痴呆患者!

//TJ
#include<bits/stdc++.h>
using namespace std;

const int N=1e7+10;
typedef long long ll;
ll n,fac[N],invf[N],mi2[N],ans;//fac 阶乘,invf 阶乘得逆元 
const ll mod=998244353;

ll qpow(ll a,ll b) {
	ll ans=1ll;
	while(b) {
		if(b&1) ans=(ans*a)%mod;
		a=(a*a)%mod;
		b/=2;
	}
	return ans;
}

ll C(int x,int y) {
	return fac[x]*invf[y]%mod*invf[x-y]%mod;
}

int main() {
	scanf("%d",&n);
	fac[0]=mi2[0]=1;
	for(int i=1; i<=n; i++)
		fac[i]=1ll*fac[i-1]*i%mod,mi2[i]=mi2[i-1]*2%mod;//fac阶乘,ci 2^2; 
	invf[n]=qpow(fac[n],mod-2);
	for(int i=n-1; i>=0; i--)
		invf[i]=1ll*invf[i+1]*(i+1)%mod;
	for(int i=n/2+1; i<=n; i++)
		ans=(ans+C(n,i)*mi2[n-i]%mod)%mod;
	ans=((qpow(3,n)-ans*2)%mod+mod)%mod;
	printf("%lld\n",ans);
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章