P5857 「SWTR-03」Matrix

原本自己有一个思路的,推了半天不太确定看了下题解,发现到后面完全不知道他代码在写些什么(我太弱了),所以打算自己理一下。

题解

首先我们可以肯定的一点就是,我们可以发现,一个矩阵的形态只和他横着和竖着有多少行和列被转化了奇数次,而与剩下的都没有关系。

很显然的可以发现行和列是可以独立计算再相乘的,考虑如何计算单行和单列的贡献。

以行为例,我们可以枚举他有多少个奇数的位置,发现奇数位置的数量 (i) 必须满足如下的性质:

[ile k\ ile n\ i equiv k pmod{2} ]

但是发现可能有一种特殊情况,就是当 (n-i)(m-j) 也合法的时候,两者形成的矩形是完全一样的,需要把这一部分的消去。

应该就这些了。

代码如下

#include<bits/stdc++.h>
using namespace std;
#define Lint long long
const int N=2e5+5;
const Lint MOD=998244353;
const Lint Inv=499122177;
int n,m,k;Lint res=0;
Lint fac[N],ifac[N];
Lint cnt1[2],cnt2[2];
Lint ksm(Lint x,int k)
{
	Lint res=1;
	for(;k;k>>=1,x=x*x%MOD)
	if(k&1) res=res*x%MOD;
	return res;
}
Lint cal(int n,int m){return fac[n]*ifac[m]%MOD*ifac[n-m]%MOD;}
void solve()
{
	cin>>n>>m>>k,res=0;
	Lint res1=0,res2=0;
	for(int i=k%2;i<=n&&i<=k;i+=2) res1+=cal(n,i),res1%=MOD;
	for(int i=k%2;i<=m&&i<=k;i+=2) res2+=cal(m,i),res2%=MOD;
	res+=res1*res2%MOD;
	if(n%2==0&&m%2==0)
	{
		res1=res2=0;
		for(int i=max(n-k,k&1);i<=n&&i<=k;i+=2) res1+=cal(n,i),res1%=MOD;
		for(int i=max(m-k,k&1);i<=m&&i<=k;i+=2) res2+=cal(m,i),res2%=MOD;
		res-=res1*res2%MOD*Inv%MOD,res=(res+MOD)%MOD;
	}
	printf("%lld
",res);
}
int main()
{
	fac[0]=ifac[0]=1;
	for(int i=1;i<N;++i) fac[i]=fac[i-1]*i%MOD;
	for(int i=1;i<N;++i) ifac[i]=ksm(fac[i],MOD-2);
	int T;cin>>T;
	while(T--) solve();
}
原文地址:https://www.cnblogs.com/Point-King/p/14070299.html