如何用一句话描述:
给定n和m,求有多少种大小为n*m的01矩阵满足每行每列异或值都是0,答案对998244353取模
yy一下
我们考虑一个(n-1)*(m-1)的矩阵
很显然,如果我们随便填,会发生什么呢?
会有一个超级大的答案出来
可是这跟我们的问题有什么关系?
毫无关系
我们找个特例,比如n=4,m=4
我们可能构造出来一个矩阵是这样的:
1 0 1 ?
0 1 1 ?
0 0 0 ?
? ? ? ?
问题来了,?处填什么?
填之前的坑啊!
用这个栗子来说
最终我们胡搞搞出来得到的是:
1 0 1 0
0 1 1 0
0 0 0 0
1 1 0 0
发现了什么?
什么都没有发现
这个矩阵满足要求
在关注原来的“?”处
发现:
对于每一行最后一个,如果当前行1的个数为偶数,那么它为0,不然就是1
对于每一列最后一个,如果当前行1的个数为偶数,那么它为0,不然就是1
复制粘贴真好玩
不管怎么样,这样子是可以的,是能得到正解的
那么,对于处于右下角的呢?
可以证明,当那几个格子确定下来时,右下角的格子不会出现矛盾情况
但是我不会
于是,这就是一个简单的快速幂了
上代码!当当当当——
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
long long t;
long long n,m;
inline void read(long long &x)
{
long long f=1;
x=0;
char ch=getchar();
while(ch<'0'||ch>'9')
{
if(ch=='-')
{
f=-1;
}
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
x=(x<<3)+(x<<1)+ch-'0';
ch=getchar();
}
x*=f;
}
long long fast_pow(long long a,long long b,long long n)
{
long long t,y;
t=1;
y=a;
while(b!=0)
{
if(b&1==1)
{
t=t*y%n;
}
y=y*y%n;
b=b>>1;
}
return t;
}
int main()
{
scanf("%lld",&t);
while(t--)
{
scanf("%lld%lld",&n,&m);
long long ans;
ans=fast_pow(2,(n-1)*(m-1),998244353);
printf("%lld\n",ans);
}
return 0;
}