【BZOJ2844】albus就是要第一个出场 线性基 高斯消元

#include <stdio.h>
int main()
{
	puts("转载请注明出处[vmurder]谢谢");
	puts("网址:blog.csdn.net/vmurder/article/details/43456773");
}

题意:需要注意的是空集(0)是天生被包括的,我为了这个WA了好久~拍了好久,醉了好久~

题解:

首先有一个我并不知道是为什么(甚至不知道它对不对)的性质:

每一种权值会出现2的自由元(n-线性基个数)次方 次。

感性证明:

首先不管重复与否,那么既然是n个数,就会出现2^n个可能相同的权值。

然后会有m个线性基,就是有m个被消消消消变成了线性基,然后n-m个自由元。

那么因为有m个线性基,所以会有2^m个互不相同的权值,

所以每个权值出现了2^n/2^m=2^(n-m)次。

嗯,很正确是吧?

如果你说这建立在所有不相同权值出现次数必须都一样的前提下才能成立。

那我也没招了。因为我的证明也是卡在了这里。

但是我认为如果这个性质被用来出题,那么出题人一定无法写暴力来出数据,所以可以安心用这个性质!

因为即使它是错的!也能跟数据对上!!!

代码: // 请无视我那逗逗的flag变量

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 101000
#define MOD 10086
using namespace std;
int n,m;
int a[N],ins[70];
int crs[N];
bool flag;
void EX_Ins(int n)
{
	int i,j,k;
	flag=0;
	memset(ins,0,sizeof ins);
	for(i=n;i;i--)
	{
		for(j=31;~j;j--)if((a[i]>>j)&1)
		{
			if(!ins[j])
			{
				ins[j]=a[i];
				for(k=0;k<31;k++)
					for(int r=k+1;r<=31;r++)
						if((ins[r]>>k)&1)
							ins[r]^=ins[k];
				break;
			}
			else a[i]^=ins[j];
		}
		if(!a[i])flag=1;
	}
	return ;
}
int power(int x,int k)
{
	int ans=1;
	while(k)
	{
		if(k&1)ans=(long long)ans*x%MOD;
		x=(long long)x*x%MOD,k>>=1;
	}
	return ans;
}

int main()
{
//	freopen("test.in","r",stdin);
	int i,k,ans=0;
	scanf("%d",&n);
	for(i=1;i<=n;i++)scanf("%d",&a[i]);
	EX_Ins(n);
	for(m=i=0;i<=31;i++)if(ins[i])crs[i]=m++;

	scanf("%d",&k);
	for(i=0;i<=31;i++)if((k>>i)&1)if(ins[i])ans+=(1<<crs[i]);
		flag=1;
	if(!flag)ans--;
	ans%=MOD;
//	printf("%d\n",ans);
	printf("%d\n",(int)(((long long)ans*power(2,n-m)+1)%MOD));
	return 0;
}
时间: 2025-01-15 20:24:15

【BZOJ2844】albus就是要第一个出场 线性基 高斯消元的相关文章

题解 外星千足虫(线性基+高斯消元)

题解 luogu外星千足虫(线性基+高斯消元) 题目 luogu题目传送门 题解想法 首先需要知道这是个异或方程对吧 然后既然看到位运算,又有这么多,就可以考虑线性基(做题技巧),那我们就丢进去 接下来看一看线性基,哇,性质美妙 它不就是Gauss消元里面想要的上三角矩阵吗 所以说: 如果能拼成线性基,那么枚举到哪里完成了,就输出位置(first_ans) 如果拼不成,那就解不出(毋庸置疑) 那真是美妙啊... 所以怎么消元呢?这可是个异或方程,我们要解出来啊 枚举整个线性基的g[i] 如果g[

【bzoj4004】【JLOI2015】装备购买 (线性基+高斯消元)

Description 脸哥最近在玩一款神奇的游戏,这个游戏里有 n 件装备,每件装备有 m 个属性,用向量zi(aj ,.....,am) 表示 (1 <= i <= n; 1 <= j <= m),每个装备需要花费 ci,现在脸哥想买一些装备,但是脸哥很穷,所以总是盘算着怎样才能花尽量少的钱买尽量多的装备.对于脸哥来说,如果一件装备的属性能用购买的其他装备组合出(也就是说脸哥可以利用手上的这些装备组合出这件装备的效果),那么这件装备就没有买的必要了.严格的定义是,如果脸哥买了

【题解】 bzoj1923: [Sdoi2010]外星千足虫 (线性基/高斯消元)

bzoj1923,戳我戳我 Solution: 这个高斯消元/线性基很好看出来,主要是判断在第K 次统计结束后就可以确定唯一解的地方和\(bitset\)的骚操作 (我用的线性基)判断位置,我们可以每次加入一个线性基时判断是不是全被异或掉了,如果没有,说明这个方程不是冗余的,那么我们可记录非冗余方程个数 如果非冗余方程个数小于\(n\),那就是个不定方程组,有无数种解,否则,在个数第一次达到\(n\)时,就可输出当时输入方程的号码 还有一个点就是压空间与时间,这题主要是时间,用到大杀器\(bit

albus就是要第一个出场(线性基)

传送门 这个题题目描述真怪异--就不能说人话吗-- 人话:给定长为n的序列A,定义f(s)为集合s内所有元素异或值,求A的所有子集的f值从小到大排列后,q在其中第一次出现的下标对10086取模的值. 首先不难想到构建线性基.线性基有一个良好的性质!假设这n个数的线性基中有k的数,那么显然有\(2^k\)种异或值.之后,因为线性基是可以看作线性基中本来有的数再加上一堆0,所以每一种异或值应该出现过\(2^{n-k}\)次. 那么我们只需要求出来q在这一堆异或值中的排名.这个我们可以仿照求第k大的操

bzoj 2844: albus就是要第一个出场 线性基

首先线性基是什么呢.我们考虑我们有n个数.子集数量为2^n个.我们将每个子集内的数全部异或起来.得到一个值.但是我们考虑这些值内会可能存在重复的,太多了.不便于运算.所以我们考虑,能不能除去重复的. 我们假定n个数都是<10^9.我们考虑使用一个30*30的矩阵.其中其中第一行,存一个最高位1位于数字第1位的数.第二行存一个最高位1位于数字2位的数.以此类推.这样子我们可以得到一个30*30的的矩阵.这个矩阵未必每一行都填满.我们可以考虑,加入一个元素,发现他对应的行已经被填满了.我们将这个数和

bzoj2844 albus就是要第一个出场

题意:http://www.lydsy.com/JudgeOnline/problem.php?id=2844 sol  :因为这个是不去重空间,所以麻烦点QAQ 考虑去重空间的做法,直接线性基+树形dp即可 而对于不去重空间,其大小为2^n,求出异或空间的秩m,则去重空间的大小为2^m 那么去重异或空间的每个值在不去重异或空间里出现2^(n-m)次 所以答案即为去重异或空间的答案*2(n-m)+1即可 记得开long long #include<iostream> #include<a

【BZOJ2844】albus就是要第一个出场 高斯消元求线性基

[BZOJ2844]albus就是要第一个出场 Description 已知一个长度为n的正整数序列A(下标从1开始), 令 S = { x | 1 <= x <= n }, S 的幂集2^S定义为S 所有子集构成的集合.定义映射 f : 2^S -> Zf(空集) = 0f(T) = XOR A[t] , 对于一切t属于T现在albus把2^S中每个集合的f值计算出来, 从小到大排成一行, 记为序列B(下标从1开始). 给定一个数, 那么这个数在序列B中第1次出现时的下标是多少呢? I

【bzoj2844】 albus就是要第一个出场

http://www.lydsy.com/JudgeOnline/problem.php?id=2844 (题目链接) 题意 给出${n}$个数,它们可以异或出${n^2}$个数,将这些数从小到大排列起来,问${Q}$最早出现的位置. Solution 原来线性基还有这种性质,我怎么不知道→_→ 假设${n}$个数可以消出${k}$个线性基,那么显然会有${2^k}$个不同的亦或和,${n}$个数相互排列显然会有${2^n}$个.神奇的事情就在于每种亦或和居然是一样多的,也就是都是${2^{n

BZOJ 2844 albus就是要第一个出场 ——高斯消元 线性基

[题目分析] 高斯消元求线性基. 题目本身不难,但是两种维护线性基的方法引起了我的思考. 1 2 3 4 5 6 7 8 9 10 11 12 void gauss(){     k=n;     F(i,1,n){         F(j,i+1,n) if (a[j]>a[i]) swap(a[i],a[j]);         if (!a[i]) {k=i-1; break;}         D(j,30,0) if (a[i]>>j & 1){