「雅礼集训 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$的线性空间外的方案数

那么答案就是$\sum\limits_{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\times i$的矩阵),秩为$j$的方案数

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

再除以秩为$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\n", ans);
	return 0;
}
时间: 2024-07-30 09:56:53

「雅礼集训 2017 Day5」矩阵的相关文章

「6月雅礼集训 2017 Day5」吃干饭

[题目大意] 询问[L,R]中选若干个数异或起来得到的答案集合大小.多组数据. 对于50%的数据,$R - L \leq 10^4$ 对于100%的数据,$R - L \leq 10^{18}, T \leq 10^2$ [题解] 考虑50%的数据,暴力线性基即可. 这样的复杂度是$O(T(R-L)logn)$ 观察到数据比较特殊,是连续的一段正整数,我们写完线性基暴力然后打个表观察数在什么时候被插入到线性基里. 我们以[23333, 66666]为例: 首先L=23333,这个数一定被插入到线

loj6029 「雅礼集训 2017 Day1」市场

传送门:https://loj.ac/problem/6029 [题解] 考虑如果有一些近似连续的段 比如 2 2 2 3 3 3,考虑在除3意义下,变成0 0 0 1 1 1,相当于整体-2 又:区间增加很容易造成这种段,所以我们猜测可以暴力维护 用一棵线段树即可.(好像真的能暴力维护啊 我不知道怎么证明复杂度) # include <stdio.h> # include <string.h> # include <iostream> # include <al

loj6045 「雅礼集训 2017 Day8」价

传送门:https://loj.ac/problem/6045 [题解] 由于存在完美匹配,所以选择k个药就要选择>=k个药材,我们要求的是选择k个药正好选择k个药材. 那么定义选一种减肥药的代价为-pi+INF,选一种药材的代价为INF,这样最小割肯定是恰好选k个 那么 最后答案就是最小割 - Σ(-pi+INF) [由于减肥药是负的所以要反过来...] 中间连的边要设成比inf大的.. # include <stdio.h> # include <string.h> #

LOJ #6035.「雅礼集训 2017 Day4」洗衣服 贪心

这道题的贪心好迷啊~我们对于两个过程进行单独贪心,然后再翻转一个,把这两个拼起来.先说一下单独贪心,单独贪心的话就是用一个堆,每次取出最小的,并且把这个最小的加上他单次的,再放进去.这样,我们得到的结果,是对于某些洗衣机,不停地洗,然后把这些洗衣机的时间,混在一起,排个序,由于对于每个洗衣机,如果被用到,那么他就会被不停地用,如果我们稍作改动,就一定会是用小的换来大的,所以这样最优.我们把两个拼起来为什么是对的呢.对于两个单独的答案,最优的无疑是,翻转之后拼起来,因为如果不是这样,也就是说进行了

【loj6029】「雅礼集训 2017 Day1」市场 线段树+均摊分析

题目描述 给出一个长度为 $n$ 的序列,支持 $m$ 次操作,操作有四种:区间加.区间下取整除.区间求最小值.区间求和. $n\le 100000$ ,每次加的数在 $[-10^4,10^4]$ 之间,每次除的数在 $[2,10^9]$ 之间. 题解 线段树+均摊分析 和 [uoj#228]基础数据结构练习题 类似的均摊分析题. 对于原来的两个数 $a$ 和 $b$ ( $a>b$ ) ,原来的差是 $a-b$ ,都除以 $d$ 后的差是 $\frac{a-b}d$ ,相当于差也除了 $d$

#6030. 【雅礼集训 2017 Day1】矩阵

#6030. 「雅礼集训 2017 Day1」矩阵 题目描述 有一个 n×n  的矩阵,每个位置 (i,j) 如果是 . 表示为白色,如果是 # 表示为黑色. 初始时,每个位置可以是黑色或白色的,(i,j)  位置的值会作为 ai,j 给你. 现在有一种操作,选择两个整数 i,j∈[1,n],记 (i,1),(i,2),…,(i,n) (i, 1), (i, 2)的颜色为 C1,C2,…Cn ??,将 (1,j),(2,j),…,(n,j)  的颜色赋为 C1,C2,…,Cn ??. 你的任务是

「6月雅礼集训 2017 Day10」quote

[题目大意] 一个合法的引号序列是空串:如果引号序列合法,那么在两边加上同一个引号也合法:或是把两个合法的引号序列拼起来也是合法的. 求长度为$n$,字符集大小为$k$的合法引号序列的个数.多组数据. $1 \leq T \leq 10^5, 1 \leq n \leq 10^7, 1\leq K \leq 10^9$ [题解] 显然引号序列可以看做括号序列,于是我们有了一个$O(n^2)$的dp了. 设$f_{i,j}$表示到第$i$个位置,前面有$j$个左引号没有匹配,的方案数 每次,要么有

「6月雅礼集训 2017 Day7」电报

[题目大意] 有n个岛屿,第i个岛屿有有向发射站到第$p_i$个岛屿,改变到任意其他岛屿需要花费$c_i$的代价,求使得所有岛屿直接或间接联通的最小代价. $1 \leq n \leq 10^5, 1 \leq p_i,c_i \leq 10^9$ [题解] 显然最后是个大环,特判原来就是大环的情况. 考虑每个连通块最多保留多少. 树的答案可以直接dp做出来. 环的答案,根据树的答案dp出来. h[x][0/1]表示当前做到环上第i个点,环是否被切断了,的最大保留价值. 因为环必须被切断一次.所

「6月雅礼集训 2017 Day8」gcd

[题目大意] 定义times(a, b)表示用辗转相除计算a和b的最大公约数所需步骤. 那么有: 1. times(a, b) = times(b, a) 2. times(a, 0) = 0 3. times(a, b) = times(b, a mod b) + 1 对于$1 \leq x \leq A, 1 \leq y \leq B$,求times(A, B)的最大值,以及有多少对数取到了最大值. 多组数据. $T \leq 3 \times 10^5, 1 \leq A,B \leq