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

    题面

    传送门

    题解

    我对线代一无所知

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

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

    首先,关于(A imes 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 imes i)的矩阵,秩为(j)的方案数,(g_{i,j})表示(i imes 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]='
    ';
    }
    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;
    }
    
  • 相关阅读:
    tp5 select回显
    toFixed
    用js来实现银行家算法
    js 日期证有效性验的通用方法
    js获取或判断任意数据类类型的通用方法(getDataType)和将NodeList转为数组(NodeListToArray)
    js实现jquery函数animate动画效果
    js原生实现 无缝滚动图片
    scrollTop实现图像循环滚动(实例1)
    commonCookie.js
    delphi XE3解析JSON数据
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/10479565.html
Copyright © 2011-2022 走看看