程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> BZOJ 2844 albus就是要第一個出場 高斯消元

BZOJ 2844 albus就是要第一個出場 高斯消元

編輯:C++入門知識

BZOJ 2844 albus就是要第一個出場 高斯消元


題目大意:給定一個n個數的集合S和一個數x,求x在S的2^n個子集從大到小的異或和序列中最早出現的位置

有學長真好不用自己打題目大意了233

首先我們求出線性基 我們會得到一些從大到小排列的數和一堆0 記錄0的個數

不考慮0,看前面的數,由於線性基的性質,我們直接貪心從大到小枚舉 若當前異或和異或這個值小於Q則取這個數 (注意^不要寫成+或者| 本蒟蒻已經因為這個WA了兩道題了

然後我們通過每個數取不取可以得到一個01序列 這個序列就是通過異或可以得到的小於Q的數的數量的二進制

比如線性基是8 4 2 Q=13 取完8和4之後無法法取2 那麼得到的01序列就是110 即6

然後我們再加上空集的0

然後考慮後面的0 設有m個0 那麼每個數出現的次數為2^m 乘起來後+1就是答案

一個細節就是當Q=0的時候計算小於Q的數的數量時不要算上0 不懂的可以自己測測0

#include
#include
#include
#include
#define M 100100
#define Mo 10086
using namespace std;
int n,m,q,ans,a[M];
void Gaussian_Elimination()
{
	int i,j,k=0;
	for(j=1<<30;j;j>>=1)
	{
		for(i=k+1;i<=n;i++)
			if(a[i]&j)
				break;
		if(i==n+1)
			continue;
		swap(a[i],a[++k]);
		for(i=1;i<=n;i++)
			if(i!=k)
				if(a[i]&j)
					a[i]^=a[k];
	}
	m=n-k;
	n=k;
}
int ksm(int x,int y)
{
	int re=1;
	while(y)
	{
		if(y&1)re*=x,re%=Mo;
		x*=x,x%=Mo;
		y>>=1;
	}
	return re;
}
int main()
{
	int i,num,now=0;
	cin>>n;
	for(i=1;i<=n;i++)
		scanf("%d",&a[i]);
	Gaussian_Elimination();
	cin>>q;
	for(i=1;i<=n;i++)
		if( (now^a[i])

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved