• 雅礼集训2017day5 矩阵 题解


    题目链接:矩阵

    一些声明,一般地(r(A),A in matrix)表示矩阵A的秩

    线性代数好题

    我们考虑枚举(A,B)有多少组解

    首先我们可以把 C , B 看成 n 个互不相关的列向量,考虑若有解,则C的每一个列向量都在A构成的线性空间内(C的任意一个向量,都可以理解为A的线性组合,系数是对应B的列向量)

    那么我们考虑(r(A) = x),那么B的每一列对应的方案有(2^{n - r(A)})(对应基的位置是确定,其他可以乱选)

    以下证明一个引理,如果我们把秩大小相同的矩阵归为一个等价类,那么等价类中的任意一个矩阵 C ,对应的方案数 (A,B) 都相等

    首先,如果两个线性无关组本质相同,那么对应的方案 (A,B) 显然相同

    否则,假设A的秩为 x ,相当于已经钦定了 r 个无关向量,然后要在剩余的 n-r 列中构造 x-r 个线性无关向量组,注意到若r相同,n-r,x-r以及r构成的线性空间大小 (2^r) 这些变量都相同,故方案数相同

    那么我们可以设(f(i,j))表示现在有i个长为n的列向量,秩为j的方案数

    考虑枚举(A)的秩 x ,设其代表的线性无关组为({k_1,k_2.....k_x}),因为C的任意列向量都可以表示为该线性无关组的线性组合,那么我们就可以把它压缩成长为 x 的(0,1)向量,第 i 位为0/1,就表示(k_i)的系数为0/1,又因为秩是 r ,所以若 A 的秩确定为 x , C 的方案便是 (f(x,r))

    所以(ans = frac{sum_{x = r(C)}^nf(x,r(C)) * f(n,x)}{f(n,r(C))})

    至于 r(C) 怎么算,可以异或高斯消元

    复杂度 (O(frac{n^3}{omega} + n^2))

    /*C*/
    #include<bits/stdc++.h>
    using namespace std;
    int read(){
    	char c = getchar();
    	int x = 0;
    	while(c < '0' || c > '9')	c = getchar();
    	while(c >= '0' && c <= '9')	x = x * 10 + c - 48,c = getchar();
    	return x;
    }
    const int _ = 2e3 + 7;
    int f[_][_];
    bitset<_>C[_],p[_];
    int pw[_*_];int r = 0;int n;
    const int mod = 1e9 + 7;
    void add(int &x,int y){
    	x += y - mod;
    	x += (x >> 31) & mod;
    }
    void ins(bitset<_> A){
    	for(int i = n; i >= 1; --i){
    		if(A[i] == 0)	continue; 
    		if(p[i].count() == 0){
    			p[i] = A;
    			r++;
    			return;
    		}
    		else	A ^= p[i];
    	}
    }
    int qpow(int x,int y){
    	int ans = 1;
    	while(y){
    		if(y & 1)	ans = 1ll * ans * x % mod;
    		x = 1ll * x * x % mod;
    		y >>= 1;
    	}
    	return ans;
    }
    int main(){
    	n = read();
    	pw[0] = 1;
    	for(int i = 1; i <= n * n; ++i)	pw[i] = (pw[i-1] << 1) % mod;
    	f[0][0] = 1;
    	for(int i = 0; i < n; ++i){
    		for(int j = 0; j <= n; ++j){
    			if(!f[i][j])	continue;
    			int v = f[i][j];
    			add(f[i+1][j],1ll * v * pw[j] % mod);
    			add(f[i+1][j+1],1ll * v * (pw[n] - pw[j] + mod) % mod);
    		}
    	}
    	for(int i = 1; i <= n; ++i) {
    		for(int j = 1; j <= n; ++j)
    			C[i][j] = read();
    		ins(C[i]);
    	}
    	int ans = 0;
    	for(int x = r; x <= n; ++x)	add(ans,1ll * f[n][x] * f[x][r] % mod * pw[(n-x)*n] % mod);
    	ans = 1ll * ans * qpow(f[n][r],mod - 2) % mod;
    	cout<<ans<<'
    ';
    	return 0;
    }
    
  • 相关阅读:
    css实现右侧三角
    css 应用 给头像添加标签
    css中伪选择器使用
    服务器上的项目不能对外发送请求
    视频只能播放一两帧,PDF文件60k以上加载失败的问题,静态访问也一样
    spring集成mybatis 打印sql语句
    新浪股票代码
    linux 设置mysql密码
    linux启动mysql服务报错
    配置eclipseJVM虚拟机内存大小
  • 原文地址:https://www.cnblogs.com/y-dove/p/14839061.html
Copyright © 2020-2023  润新知