设为首页 加入收藏

TOP

BZOJ 2844 albus就是要第一个出场 高斯消元
2015-07-20 17:32:12 来源: 作者: 【 】 浏览:2
Tags: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])
      

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇[leetcode]Distinct Subsequences.. 下一篇Opencv笔记(1) 数据结构的命名..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容:

·在 Redis 中如何查看 (2025-12-26 03:19:03)
·Redis在实际应用中, (2025-12-26 03:19:01)
·Redis配置中`require (2025-12-26 03:18:58)
·Asus Armoury Crate (2025-12-26 02:52:33)
·WindowsFX (LinuxFX) (2025-12-26 02:52:30)