CF1065E Side Transmutations

我说我题目读错了你信吗。

我们不妨记操作的序列为 \(b_{p_1},b_{p_2},\dots,b_{p_k}\),接下来证明如下结论:

  • 交换 \(p_i\)\(p_{i+1}\),结果不变。

我们不妨令 \(b_{p_i}=x,b_{p_{i+1}}=y\),且 \(x \leq y\)

不妨举个例子,记 \(x=3\)\(y=5\)\(s=\texttt{12345678910}\)

先进行 \(x\) 再进行 \(y\)\(\texttt{12345678910} \rightarrow \texttt{01945678321} \rightarrow \texttt{12387654910}\)

先进行 \(y\) 再进行 \(x\)\(\texttt{12345678910} \rightarrow \texttt{01987654321} \rightarrow \texttt{12387654910}\)

我们发现两个过程的结果是一样的。事实上,这等价于对中间的一段进行题意中的操作。

于是我们可以将相同的 \(p_i\) 移动到一起,接下来我们考虑证明如下结论:

  • 每个 \(p_i\) 最多出现 \(1\) 次。

考虑如果出现超过 \(2\) 次,则我们可以对于 \(s\) 连续进行两次同样的操作,容易发现,其结果等于 \(s\) 自身。

接下来我们就知道了,对于每个操作最多使用一次,假设从小到大选的操作为 \(c_1,c_2,\dots,c_k\)

其实你应该注意到一件事,进行操作 \(b_i\) 相当于将 \(s\) 的前 \(b_i\) 位和后 \(b_i\) 位交换。假设被交换奇数次的位置有 \(t\) 个,则操作的自由值个数为 \(n-t\)

考虑写成 Pólya 定理的形式,即 \(\dfrac{1}{2^m} \sum\limits_{c} |A|^{n-(c_k-c_{k-1}+c_{k-2}-\dots)}\)

事实上,你可以发现一个厉害的事实,我们考虑将 \(b\) 差分得到 \(d\),则 \(c_k-c_{k+1}+c_{k-2}-\dots\) 可以看作是若干个差分值之和,使用经典方法解决即可。

#include<iostream>
#include<cstdio>
using namespace std;
const long long mod=998244353;
long long pow_mod(long long num1,long long num2=mod-2){
	num1=(num1%mod+mod)%mod;
	num2=(num2%(mod-1)+(mod-1))%(mod-1);
	long long num3=1;
	while(num2){
		if(num2&1){
			num3=num3*num1%mod;
		}
		num1=num1*num1%mod;
		num2>>=1;
	}
	return num3;
}
long long b[200010];
int main(){
	long long n,A;
	int m;
	scanf("%lld %d %lld",&n,&m,&A);
	for(int i=1;i<=m;i++){
		scanf("%lld",&b[i]);
	}
	for(int i=m;i>=1;i--){
		b[i]-=b[i-1];
	}
	long long ans=1;
	for(int i=1;i<=m;i++){
		long long pre=(pow_mod(A,-b[i])+1)%mod;
		ans=ans*pre%mod;
	}
	ans=ans*pow_mod(A,n)%mod;
	ans=ans*pow_mod(2,-m)%mod;
	printf("%lld",ans);
	return 0;
}
posted @ 2025-12-29 20:42  Oken喵~  阅读(0)  评论(0)    收藏  举报