欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

uoj#453. 【集训队作业2018】围绕着我们的圆环(线性代数+递推)

程序员文章站 2022-07-12 14:48:24
...

题面

传送门

题解

我对线代一无所知

如果下面有啥说错的地方请说出来省的我一辈子都搞不明白

如果你没看懂以下在讲什么不要紧,因为我也没看懂

首先,关于\(A\times B \equiv C \pmod{2}\)的方程的一组合法解,\(C\)的列向量必定在\(A\)的列向量的线性空间里

那么\(B\)就可以看成一个方程组……

\(A\)的秩为\(x\),那么\(B\)的合法的解的个数就是\((2^{q-x})^s\)

大概意思就是说因为\(A\)的秩只有\(x\),每一列对应一个异或方程组,有\(q-x\)个*元

我们需要统计\((A,C)\),其中\(C\)的列向量在\(A\)的列向量的线性空间中,且\(A\)的秩为\(x\)\(C\)的秩为\(r\),这一组的贡献要乘上一个\((2^{q-x})^s\)。然后发现所有秩为\(r\)\(C\)是等价的,只要最后除以秩为\(r\)\(C\)的个数就行了

所以要怎么数啊……我实在看不太懂啊……

\(f_{i,j}\)表示\(p\times i\)的矩阵,秩为\(j\)的方案数,\(g_{i,j}\)表示\(i\times s\)的矩阵,秩为\(j\)的方案数,递推的方式比较简单,看代码应该能懂这里就不讲了

所以如果我们确定了\(A\)的秩\(x\),以及\(C\)的秩\(r\),那么\((A,C)\)的数量就为\(g_{x,r}\)(感性理解一下好了……)

所以如果我们确定了\(C\)的秩\(r\),答案就是\(\sum_{i=r}^q f_{q,i}g_{i,r}\)

对于每一个\(r\)记录答案就是了

然而这里需要我们动态维护矩阵\(C\)的秩诶?

大概就是一个线性基吧……把\(C\)给放进一个线性基里,每次修改一行的时候先删除。删除就是把线性基里所有包含这一行的元素删除这一行的贡献。如果某一个元素只有这一行,那么说明删去这一行之后矩阵的秩会减\(1\)

//minamoto
#include<bits/stdc++.h>
#define R register
#define ll long long
#define fp(i,a,b) for(R int i=a,I=b+1;i<I;++i)
#define fd(i,a,b) for(R int i=a,I=b-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
using namespace std;
char buf[1<<21],*p1=buf,*p2=buf;
inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
int read(){
    R int res,f=1;R char ch;
    while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
    for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
    return res*f;
}
inline int get(){R char ch;while((ch=getc())>'9'||ch<'0');return ch-'0';}
char sr[1<<21],z[25];int K=-1,Z=0;
inline void Ot(){fwrite(sr,1,K+1,stdout),K=-1;}
void print(R int x){
    if(K>1<<20)Ot();if(x<0)sr[++K]='-',x=-x;
    while(z[++Z]=x%10+48,x/=10);
    while(sr[++K]=z[Z],--Z);sr[++K]='\n';
}
const int N=1005,P=1e9+7;
inline int add(R int x,R int y){return x+y>=P?x+y-P:x+y;}
inline int dec(R int x,R int y){return x-y<0?x-y+P:x-y;}
inline int mul(R int x,R int y){return 1ll*x*y-1ll*x*y/P*P;}
int ksm(R int x,R ll y){
    R int res=1;
    for(;y;y>>=1,x=mul(x,x))if(y&1)res=mul(res,x);
    return res;
}
bitset<N>a[N],b[N];int bin[N],id[N],pos[N],f[N][N],g[N][N],ans[N];
int p,q,s,m,k,las,r,n,res;
void ins(R int i){
    fd(j,s,1)if(a[i][j]){
        if(!id[j]){++r,id[j]=i,pos[i]=j;return;}
        a[i]^=a[id[j]],b[i]^=b[id[j]];
    }
    pos[i]=0;
}
int erase(int i){
    int mn=s+1,x=0;
    fp(j,1,p)if(b[j][i]&&cmin(mn,pos[j]))x=j;
    fp(j,1,p)if(b[j][i]&&j!=x)a[j]^=a[x],b[j]^=b[x];
    if(pos[x])--r,id[pos[x]]=0,pos[x]=0;
    a[x].reset(),b[x].reset();
    return x;
}
void init(){
    n=N-1;
    bin[0]=1;fp(i,1,n)bin[i]=mul(bin[i-1],2);
    f[0][0]=g[0][0]=1;
    fp(i,1,n)fp(j,0,i){
        f[i][j]=add((j?mul(f[i-1][j-1],dec(bin[p],bin[j-1])):0),mul(f[i-1][j],bin[j]));
        g[i][j]=add((j?mul(g[i-1][j-1],dec(bin[s],bin[j-1])):0),mul(g[i-1][j],bin[j]));
    }
    for(R int i=1,S=bin[s];i<=n;++i)bin[i]=mul(bin[i-1],S);
    fp(r,0,s){
        res=0;
        fp(i,r,q)res=add(res,1ll*f[q][i]*g[i][r]%P*bin[q-i]%P);
        ans[r]=mul(res,ksm(g[p][r],P-2));
    }
}
int main(){
//  freopen("testdata.in","r",stdin);
    p=read(),q=read(),s=read(),m=read(),k=get();
    init();
    fp(i,1,p){
        fp(j,1,s)a[i][j]=get();
        b[i][i]=1,ins(i);
    }
    print(las=ans[r]);
    while(m--){
        int j=read()^(las*k),x=erase(j);
        fp(i,1,s)a[x][i]=get();
        b[x][j]=1,ins(x),print(las=ans[r]);
    }
    return Ot(),0;
}