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有 x x x个,偶数位置上的B有 y y y个,则有
{ x < = n 2 y < = n 2 \begin{cases} x<=\frac {n}{2}\\ y<=\frac n2 \end{cases} {x<=2ny<=2n
偶数位置上的非B符号,也就是A和C有 n 2 − y \frac n2-y 2ny个,每个非B都可以删掉一个奇数位置上的A,如果删完了有剩下的,那必然有奇数位置上的A和偶数位置上的B相邻,什么时候才能有剩下的?也即是 x > = n 2 − y x>=\frac n2-y x>=2ny;移向后得 x + y > = n 2 x+y>=\frac n2 x+y>=2n.
因此我们找出所有情况减去删不掉的情况也即是:
3 n − 2 ∗ c o u n t ( ( x + y ) > n 2 ) 3^n-2*count((x+y)>\frac n2) 3n2count((x+y)>2n)

如何计算: c o u n t ( ( x + y ) ) count((x+y)) count((x+y))

分为两部分:

  • 奇A偶B无关的数据
    x + y = t x+y=t x+y=t,则奇A偶B无关的数据有 n − t n-t nt个,在奇数位置上可填的数据是B,C,在偶数位置上可以填的数据是A,C,各有两种情况,因此总数是 2 n − t 2^{n-t} 2nt;
  • 奇A偶B数据
    也就是从n个数里选出t个数,其中奇数有 x x x个,偶数有 y y y个。
    开始我是这么想的
    例如: n = 6 , t = 4 n=6,t=4 n=6,t=4的情况:
    { x = 1 , y = 3 ; C 3 1 ∗ C 3 3 x = 2 , y = 2 ; C 2 2 ∗ C 2 2 x = 3 , y = 1 ; C 3 3 ∗ C 3 1 \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} x=1,y=3;C31C33x=2,y=2;C22C22x=3,y=1;C33C31
    计算完了之后发现是3+3*3+3=15,正好是 C 6 4 C^4_6 C64,也就是我们只需要从 n n n中选出 t t t个数,也就是 C n t C^t_n Cnt。其中奇数的位置放上A,偶数的位置放上B,这样就符合要求了。
    因此删不完得字串个数就是: C n t ∗ 2 n − t C^t_n*2^{n-t} Cnt2nt

如何计算: c o u n t ( ( x + y ) > n 2 ) count((x+y)>\frac n2) count((x+y)>2n)

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

到这里我自己就理清思路了。顺便复习了下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);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值