CF1065E Side Transmutations 做题记录

考虑一个字符集合AAAA中元素互不相同)和一个长度为nn的字符串SS,其中SS中的字符都属于集合AA

给你一个包含 mm 个整数的序列 bb (b1<b2<<bmb_1<b_2<\dots<b_m)。你可以对字符串 SS 作以下的操作:

1.选择一个合法的 ii ,并且令 k=bik=b_i ;

2.取出 SS 中前 kk 个字符 PrkPr_k ;

3.取出 SS 中后 kk 个字符SukSu_k ;

4.将 SS 中前 kk 个字符替换成翻转后的 SukSu_k ;

5.将 SS 中后 kk 个字符替换成翻转后的 PrkPr_k ;

举个例子,我们令 S=S= "abcdefghi",k=2k=2 。这时Pr2=Pr_2= "ab",Su2=Su_2= "hi",翻转后有 Pr2=Pr_2= "ba",Su2=Su_2= "ih",那么最终得到的字符串 SS 就是 "ihcdefgba"。

这个操作可以被执行许多次(可能是零次),任何一个 ii 也可以被使用多次。

我们将字符串 SSTT 称为相等的字符串,当且仅当存在一个操作序列,将字符串 SS 变成 TT。对于上面的例子来说,"abcdefghi" 和 "ihcdefgba" 是相等的。注意到 SS 和它自己也是相等的。

你的任务很简单,数出互不相同的字符串的个数。

最终的答案可能会非常大,因此你只需要输出答案 modmod 998244353998244353 的结果。

2n1092 \leq n \leq 10^91mmin(n2,2105)1 \leq m \leq min(\frac{n}{2},2 * 10^5)1A1091\leq |A|\leq 10^9

记字符集大小为 VV

观察到一次操作相当于是把 SS 的前 kk 位和 SS 的后 kk 位按位交换,即

swapi=1k(Si,Sni+1)\operatorname{swap}_{i=1}^k(S_i,S_{n-i+1})

那么考虑把 SS “对折”,问题就变成了有两个长度为 n2\lfloor\frac{n}{2}\rfloor 的字符串 AABB,每次操作可以选一个 k{bi}k\in \{b_i\},交换 A[1,k]A_{[1,k]}B[1,k]B_{[1,k]},问有多少种本质不同的 ABABAABB 拼起来的字符串)。特别的,如果 nn 是奇数,那么中间那个位置永远不会被操作到,可以单独处理。

不难发现,由于操作中的 kk 一定是序列 bb 中的某个数,并且同一个 kk 最多只会操作一次。所以我们关心的只是 A[bi1+1,bi]A_{[b_{i-1}+1,b_i]} 是否等于 B[bi1+1,bi]B_{[b_{i-1}+1,b_i]}。因为若不等则交换后结果不一样,否则结果一样。为了表述方便,不妨记它们为 A[i]A_{[i]}B[i]B_{[i]}

下面的部分瞟了一眼题解才会。


考虑枚举每一个 ii

  • A[i]=B[i]A_{[i]}=B_{[i]} 的情况:共有 VA[i]V^{|A_{[i]}|} 种方案;
  • A[i]=B[i]A_{[i]}\not=B_{[i]} 的情况:共有 VA[i](VB[i]1)2\dfrac{V^{|A_{[i]}|}(V^{|B_{[i]}|}-1)}{2} 种方案,除以 22 是因为交换后的也枚举过。

这两种情况的方案数加起来,再乘起来,最后永远不会被操作到的单独处理即可。

部分代码:

int ans=1;
for(int i=1;i<=m;i++)
{
    scanf("%d",&b[i]);
    int eq=qpow(v,b[i]-b[i-1]);
    int neq=1ll*qpow(v,b[i]-b[i-1])*(qpow(v,b[i]-b[i-1])-1)%p*qpow(2,p-2)%p;
    ans=1ll*ans*(eq+neq)%p;
}
ans=1ll*ans*qpow(v,n-b[m]-b[m])%p;