*题解:P10116 [LMXOI Round 1] Random

题目链接

解析

由于一个结果序列中若出现多个匹配序列应当重复计算,所以考虑拆贡献,依次考虑 \(B\) 出现在每个位置上的情况。然后就可以发现 \(B\) 在每个位置上做的贡献是一样的,故只需求钦定 \(B\) 在某个位置上的方案数,乘上 \(n - m + 1\) 即为答案。

不妨钦定 \(B\) 出现在 \([1,m]\),那么在一个合法的询问序列中,对位置 \(1\) 进行的最后一次操作必定为将该位置上的元素修改为 \(x_1\),位置 \(2\)\(m\) 同理。也就是说,如果已经定了要操作的位置,那么对于 \([1,m]\) 中的每个位置的最后一次操作,其修改成的值是定的,而对于其余操作,其修改成的值有 \(k\) 种选择,总共就是 \(k^{q - m}\) 种方案。

现在要定操作的位置,我们要求在询问序列中 \([1,m]\) 中每个位置都出现至少一次的方案数。考虑容斥,其方案数为总方案数减去至少有一个位置不出现的方案数。前者为 \(n^q\),后者为 \(\sum_{i=1}^m (-1)^{i-1}\binom{m}{i}(n-i)^q\),求和里求的是钦定有 \(i\) 个位置没有出现的方案数。

故答案为:

\[(n - m + 1)k^{q - m}(n^q-\sum_{i=1}^m (-1)^{i-1}\binom{m}{i}(n-i)^q) \]

时间复杂度 \(O(m \log q)\)

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N = 3e6 + 10,mod = 998244353;
int fac[N],inv[N];
int qmi(int a,int b){
	int res = 1;
	while(b){
		if(b & 1) res = 1ll * res * a % mod;
		b >>= 1;
		a = 1ll * a * a % mod;
	}
	return res;
}
int C(int n,int m){
	if(m > n) return 0;
	return 1ll * fac[n] * inv[m] % mod * inv[n - m] % mod;
}
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0);	
//	freopen("in.txt","r",stdin);
//	freopen("out1.txt","w",stdout);
	fac[0] = 1;
	for(int i=1;i<N;i++){
		fac[i] = 1ll * fac[i - 1] * i % mod;
	}
	inv[N - 1] = qmi(fac[N - 1],mod - 2);
	for(int i=N - 2;i>=0;i--){
		inv[i] = 1ll * inv[i + 1] * (i + 1) % mod;
	}
	int n,m,q,k;
	cin>>n>>m>>q>>k;
	if(m > q){
		cout<<0;
		return 0;
	}
	int res = qmi(n,q);
	int sum = 0;
	for(int i=1;i<=m;i++){
		int x = (i & 1) ? 1 : -1;
		sum = (sum + 1ll * x * C(m,i) * qmi(n - i,q) % mod) % mod;
	}
	sum = (sum + mod) % mod;
	res = (res + mod - sum) % mod;
	res = 1ll * res * (n - m + 1) % mod * qmi(k,q - m) % mod;
	cout<<res;
	return 0;
}
posted @ 2026-08-25 14:40  yutar  阅读(7)  评论(0)    收藏  举报