原本自己有一个思路的,推了半天不太确定看了下题解,发现到后面完全不知道他代码在写些什么(我太弱了),所以打算自己理一下。
题解
首先我们可以肯定的一点就是,我们可以发现,一个矩阵的形态只和他横着和竖着有多少行和列被转化了奇数次,而与剩下的都没有关系。
很显然的可以发现行和列是可以独立计算再相乘的,考虑如何计算单行和单列的贡献。
以行为例,我们可以枚举他有多少个奇数的位置,发现奇数位置的数量 (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();
}