zoukankan      html  css  js  c++  java
  • 「雅礼集训 2017 Day5」矩阵

    填坑填坑..

    感谢wwt耐心讲解啊..

    如果要看这篇题解建议从上往下读不要跳哦..


    30pts

    把$A$和$C$看成$n$个$n$维向量,那$A_i$是否加入到$C_j$中就可以用$B_{i,j}$表示了

    枚举矩阵$A$,求出它的秩$r$,如果$C$在$A$的线性空间内则$C$可以被$A$表示出来

    那么$B$矩阵的方案数就是$(2^{n-r})^n$

    这时候我们可以发现,由于枚举$A$覆盖了所有情况,秩相同的$C$的答案都是一样的

    然后就可以打表算答案了..


    60pts

    如果不想看可以跳过这段

    考虑用dp来代替上面枚举

    定义$f_{i,j,k}$表示已经算了前$i$列,其中$C$有$j$个基在$A$的线性空间里,$A$有$k$个基在$C$的线性空间外的方案数

    那么答案就是$sumlimits_{k=1}^{n-r}f[n][r][k](2^{n-r-k})^n$

    然后考虑第$i+1$列的情况

    1)$j$、$k$都不变,即新的一列在$j+k$个基里面,方案为$2^{j+k}$

    2)$j+1$、$k$不变,$k$不变的方案有$2^{r+k}$,再减去$j$不变的方案就是$2^{r+k}-2^{j+k}$

    3)$j$不变,$k+1$,总方案有$2^n$,再减去$k$不变的方案就是$2^n-2^{r+k}$

    这样就得到了一个$O(n^3)$的做法


    100pts

    30pts时说到,秩相同的$C$的答案都是一样的

    那么我们不如把所有秩相同的$C$的总答案算起来再除以秩相同的个数

    定义$f_{i,j}$表示已经算了前$i$列(也就是$n imes i$的矩阵),秩为$j$的方案数

    那么总答案就是$sumlimits_{x=r}^n f_{n,x}f_{x,r}(2^{n-x})^n$

    18.12.26 update:

    把$C$的每一列写成大小为$x$的01向量,那么相当于是一个$n imes x$的矩阵使其的秩为$r$,也就是$f_{x,r}$

    再除以秩为$r$的方案数即可..


    Code

    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <algorithm>
    #include <bitset>
    #define LL long long
    using namespace std;
    const LL Maxn = 2010;
    const LL Mod = 1e9+7;
    bitset <Maxn> a[Maxn];
    LL f[Maxn][Maxn];
    LL pow2[Maxn], n;
    LL pow(LL x, LL k) {
    	LL ret = 1;
    	while(k){
    		if(k&1) ret = (ret*x)%Mod;
    		x = (x*x)%Mod;
    		k >>= 1;
    	}
    	return ret;
    }
    int main() {
    	//freopen("mat.in", "r", stdin);
    	//freopen("mat.out", "w", stdout);
    	LL i, j, k;
    	scanf("%lld", &n);
    	pow2[0] = 1;
    	for(i = 1; i <= n; i++) pow2[i] = (pow2[i-1] << 1) % Mod;
    	f[0][0] = 1;
    	for(i = 0; i < n; i++){
    		for(j = 0; j <= i; j++){
    			if(f[i][j] == 0) continue;
    			f[i+1][j] = (f[i+1][j] + (f[i][j]*pow2[j])%Mod) % Mod;
    			f[i+1][j+1] = (f[i+1][j+1] + (f[i][j]*((pow2[n]-pow2[j]+Mod)%Mod))%Mod) % Mod;
    		}
    	}
    	for(i = 0; i < n; i++){
    		for(j = 0; j < n; j++){
    			LL x;
    			scanf("%lld", &x);
    			a[i][j] = x;
    		}
    	}
    	LL r = 0;
    	for(i = 0; i < n; i++){
    		for(j = r; j <= n; j++){
    			if(a[j][i] == 1){ swap(a[r], a[j]); break; }
    		}
    		if(a[r][i] == 0) continue;
    		for(j = r+1; j < n; j++) if(a[j][i] == 1) a[j] ^= a[r];
    		r++;
    	}
    	LL ans = 0;
    	for(i = r; i <= n; i++){
    		ans = (ans + ((f[n][i]*f[i][r])%Mod*pow(pow2[n], n-i))%Mod)%Mod;
    	}
    	ans = (ans*pow(f[n][r], Mod-2))%Mod;
    	printf("%lld
    ", ans);
    	return 0;
    }
    
  • 相关阅读:
    第三个冲刺周期第1天
    第二个冲刺周期第7天
    第二个冲刺周期第6天
    第二个冲刺周期第5天
    电梯调度系统最终版
    电梯调度系统迟真真&冯小兰
    软件工程之课程评价czz
    《代码大全2》读后感czz
    迟真真假如历史可以重来
    十天冲刺任务迟真真
  • 原文地址:https://www.cnblogs.com/darklove/p/8063829.html
Copyright © 2011-2022 走看看