相当于要对⼀个模 2 下的矩阵,求出每个位置取反后矩阵新的话这,显然只修改⼀个位置的话秩只有可能+1,-1,不变
分类讨论就行了,30分
⾸先我们假设 A 是⾏⼤于列的
我们把 A ⾼斯消元成最简形式,假设消完后是 BA
显然rank(BA)=rank(A)
且对 A(i,j) 取反相当于 BA 的第 j 列加上 B 的第 i 列
还是分类讨论,100分
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int mod=998244353;
template <typename _Tp> inline _Tp read(_Tp&x){
char c11=getchar(),ob=0;x=0;
while(c11^'-'&&!isdigit(c11))c11=getchar();if(c11=='-')c11=getchar(),ob=1;
while(isdigit(c11))x=x*10+c11-'0',c11=getchar();if(ob)x=-x;return x;
}
int n,m,ret;bitset<1005>s[1005],tmp,tmp2,tmp3;
struct xxj
{
bitset<1005>s[1005];int vis[1005],len;
void insert(bitset<1005>c)
{
tmp3=c;
for(int i=1;i<=1000;++i)
{
if(!tmp3[i])continue;
if(!s[i][i])
{
for(int j=i+1;j<=1000;++j)
{
if(tmp3[j]&&s[j][j])tmp3^=s[j];
}
s[i]=tmp3;len++;
for(int j=1;j<i;++j)if(s[j][i])s[j]^=s[i];
}
tmp3^=s[i];
}
}
}
g[16];
void cdq(int l,int r,int dep)
{
if(l==r)
{
tmp=s[l];
for(int i=1;i<=m;i++)
if(tmp[i]&&g[dep].s[i][i])tmp^=g[dep].s[i];
for(int j=1;j<=m;j++)
{
tmp2=tmp;
tmp2[j]=tmp2[j]^1;
tmp2^=g[dep].s[j];
ret+=1ll*g[dep].len*l*j;
if(tmp2.count())ret+=1ll*l*j;
ret%=mod;
}
return ;
}
int mid=(l+r)>>1;
g[dep+1]=g[dep];
for(int i=mid+1;i<=r;++i)g[dep+1].insert(s[i]);
cdq(l,mid,dep+1);
g[dep+1]=g[dep];
for(int i=l;i<=mid;++i)g[dep+1].insert(s[i]);
cdq(mid+1,r,dep+1);
}
signed main()
{
read(n);read(m);
for(int i=1;i<=n;++i)
{
for(int j=1;j<=m;++j)
{
int tmp;
scanf("%1d",&tmp);
s[i][j]=tmp;
}
}
cdq(1,n,1);
cout<<ret<<endl;
}