CF2048G Kevin and Matrices

CF2048G Kevin and Matrices

这题小时候抱过我。

小的时候从图书馆借了一本数学科普书,里面给出过如下定理:

\[\min\limits_{i=1}^{n} (\max\limits_{j=1}^{m} a_{i,j}) \geq \max\limits_{j=1}^{m} (\min\limits_{i=1}^{n} a_{i,j}) \]

我们不妨假设左式对应的是 \(a_{x_1,y_1}\),右式对应的是 \(a_{x_2,y_2}\)。

显然,\(a_{x_1,y_1} \geq a_{x_1,y_2}\),因为 \(a_{x_1,y_1}\) 是当前行最大的。

其次,\(a_{x_2,y_2} \leq a_{x_1,y_2}\),因为 \(a_{x_2,y_2}\) 是当前列最小的。

有了上面的结论,我们不妨给出合法的条件:

\[\min\limits_{i=1}^{n} (\max\limits_{j=1}^{m} a_{i,j}) = \max\limits_{j=1}^{m} (\min\limits_{i=1}^{n} a_{i,j}) \]

显然我们需要先枚举等式的值,不妨令其为 \(k\)。

显然,我们需要使得每一行都存在 \(\geq k\) 的数,且有至少一行最大值为 \(k\)。

同理,我们需要是的每一列都存在 $\leq k $ 的数,且有至少一列最小值为 \(k\)。

记 \(f(x,y)\) 表示每一行存在 \(\geq x\) 的数,每一列存在 \(\leq y\) 的数对应的方案数。

显然,其等价于每行 \(\max \geq x\),每列 \(\min \leq y\)。

容斥,答案为 \(f(k,k)-f(k+1,k)-f(k,k-1)+f(k+1,k-1)\)。

接下来考虑如何求 \(f(x,y)\)。

因为已经容斥了,我们不需要考虑上面相等的限制。

同时,我们只能接受 \(O(n)\) 的计算复杂度。

\(\max \geq x\) 显然难以处理,考虑钦定 \(i\) 行的 \(\max < x\),记方案数为 \(f_i\)。

根据容斥原理,答案为 \(\sum\limits_{i=0}^{n} (-1)^{i} \dbinom{n}{i} f_i\)。

接下来计算 \(f_i\),不难发现在此情景下每一列都是独立的。

对于一列计算方案数,有 \(i\) 个数 \(<x\),\(n-i\) 个数 \(\leq v\),要求 \(\min \leq y\)。

考虑继续容斥,我们反面考虑。

总的方案数是 \(v^{n-i} (x-1)^i\),这是容易统计的。接下来反面的方案数。

答案为 \((v-y)^{n-i} \max(x-y-1,0)^{i}\),两式相减求 \(m\) 次方即可得到 \(f_i\)。

总时间复杂度可以做到 \(O(\sum nv)\),由于我比较懒所以多了 \(\log\)。

//Ad astra per aspera
#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;
}
int n,v;
long long m;
long long fact[1000010],invfact[1000010];
void init(){
	fact[0]=invfact[0]=1;
	for(int i=1;i<=n;i++){
		fact[i]=fact[i-1]*i%mod;
		invfact[i]=invfact[i-1]*pow_mod(i)%mod;
	}
}
long long f(int x,int y){
	long long sum=0;
	for(int i=0;i<=n;i++){
		long long ans=pow_mod(v,n-i)*pow_mod(x-1,i)%mod-pow_mod(v-y,n-i)*pow_mod(max(x-y-1,0),i)%mod;
		ans=pow_mod(ans,m);
		sum+=pow_mod(-1,i)*fact[n]%mod*invfact[i]%mod*invfact[n-i]%mod*ans%mod;
		sum%=mod;
	}
	return sum;
}
int main(){
	int T;
	scanf("%d",&T);
	while(T--){
		scanf("%d %lld %d",&n,&m,&v);
		init();
		long long ans=0;
		for(int i=1;i<=v;i++){
			ans+=f(i,i)-f(i+1,i)-f(i,i-1)+f(i+1,i-1);
			ans=(ans%mod+mod)%mod;
		}
		printf("%lld\n",ans);
	}
	return 0;
}
posted @ 2026-03-27 17:06  Oken喵~  阅读(20)  评论(0)    收藏  举报