codeforces EC52 div2E. Side Transmutations(组合数学)

本文深入探讨了一种基于字符串匹配的算法,通过分析字符集大小、选取字符组成字符串的方法,以及通过对字符串进行特定操作来判断两个字符串是否等价的数学问题。文章详细解释了如何计算在给定条件下能够形成的不同字符串的数量,并提供了一段C++代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意

给定一个字符集的大小∣A∣|A|A,可以从中选取nnn个字符(可重复)组成一个字符串,这里规定,字符串SSS若经过以下一系列变化所得的字符串TTT,那么认为S==TS == TS==T

  1. 选取有效的bib_ibi,令 k=bik = b_ik=bi
  2. 取字符串SSS的前kkk个字符组成一个字符串SpreS_{pre}Spre
  3. 取字符串SSS的后kkk个字符组成一个字符串SsufS_{suf}Ssuf
  4. Spre,SsufS_{pre},S_{suf}Spre,Ssuf各自翻转并交换组成新的字符串T。

输入规定b0&lt;bi&lt;bi+1&lt;⋯&lt;bkb_0&lt;b_i&lt;b_{i+1} &lt; \dots &lt; b_kb0<bi<bi+1<<bk,且bib_ibi可以任选多次。问能组成多少个不同的字符串。

题解

对于给定的0&lt;bi&lt;bi+1&lt;⋯&lt;bk0 &lt; b_i &lt; b_{i+1} &lt; \dots &lt; b_k0<bi<bi+1<<bk,对于这些操作,现把问题转换一下,实际上就是对[bk−1,bk),[bk−2,bk−1)…,[0,b1)[b_{k-1},b_{k}),[b_{k-2},b_{k-1})\dots,[0,b_1)[bk1,bk),[bk2,bk1)[0,b1)进行操作,每个区间之间都互不相关,可以看成独立的n个事件组成一个大事件,即对应的乘法原理,n个事件的方案相乘。设每个区间满足条件的字符串个数为cnticnt_icnti
cnticnt_icnti为长度为iii的字符串的对数。分为两种情况考虑,将左边的串称为L,右边称为R,设S=∣A∣iS = |A|^iS=Ai

  1. 翻转后 R = L ,那么只有S种
  2. 翻转后 R != L,那么有∁S2\complement_{S}^{2}S2

总和为∣A∣2i+∣A∣i2\frac{|A|^{2i}+|A|^i}{2}2A2i+Ai
对于每个区间都有cntlencnt_{len}cntlen个字符串可选 。那么总的方案数为
cntb1∏i=2kcntbi−bi−1∗∣A∣n−2bkcnt_{b_1}\prod_{i=2}^{k}cnt_{b_i-b_{i-1}} *|A|^{n-2b_k}cntb1i=2kcntbibi1An2bk

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod =  998244353;
const int maxn = 2e5+5;
ll pow_mod(ll x, ll n) {
	ll res = 1;
	while(n) {
		if(n&1) res = res*x%mod;
		x = x*x%mod;
		n >>= 1;
	}
	return res;
}
ll n,m,A,inv;
ll b[maxn];
ll get(ll i) { // cnt_i
	return (pow_mod(A,2*i)+pow_mod(A,i))%mod*inv%mod;
}

int main() {
	inv = pow_mod(2,mod-2);
	scanf("%lld%lld%lld", &n, &m, &A);
	ll mx;
	for(int i = 1; i <= m; ++i) {
		scanf("%lld", &b[i]);
		mx = b[i];
	}
	for(int i = m; i >= 1; --i)
		b[i] = b[i]-b[i-1];
	ll AL = pow_mod(A,n-2*mx);
	ll ans = 1;
	for(int i = 1; i <= m; ++i) {
		ans = (ans*get(b[i]))%mod;
	}
	ans = ans*AL%mod;
	printf("%lld\n", ans);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值