【题目描述】
BZOJ 2844 | HYSBZ - 2844albus
【题目分析】
题目的意思大概是给一个数列,他有2n个子集,每个子集的元素的异或和构成新的一个数列,排序后问数字Q在这个序列里面的下标。
假如题目是求所有元素的异或和构成一个集合就好弄了,我们可以根据求第K大反过来求他在集合里面的下标。

int find_ans(int q){int num=0; int ans=0;vector<int> p;for(int i=0;i<=62;i++){if(b[i]){p.push_back(i);    //如果这个位置有数字,就把这个位置记下来num++;}}for(int i=num-1;i>=0;i--){if(q>>p[i]&1)    //如果这个数字在这一位有数字,那么排名就向前移动1<<i位(在0的基础上){ans+=1<<i;    //这里的i是指这一位前面有多少个高位,也就是说如果这一位是0的数字个数,加上它就是在0的基础上向前移动的排名}}//printf("test: ans=%d num=%d p[0]=%d\n",ans,num,p[0]);return ans+1;//因为前面还有一个0,所以要+1}

可是我们知道这样肯定是求不出答案的,还有好多重复的数字,我们不妨来分析一下这些重复 的数字。对于线性基异或出来的一个数字x,所有和他重复的数字肯定是由那些不包含在线性基里面的数字帮忙异或出来的。
原因是线性基的两个性质:
1.线性基异或出来的数字不相同。
2.线性基无法异或出0。
而这里其他重复的数字相当于线性基的一部分数字异或出 x后再异或一些0(异或0不会改变数值),而通过上面的分析我们知道这些0只能是那些没有进入线性基的数字和一部分进入线性基的 数字异或出来的(当然也可能不包含线性基里面的数字,但肯定不是纯线性基的数字),那么我们能异或出多少个0呢?对于线性基外的每一个数字我们都可以用线性基里面的一部分数字异或出来,所以线性基外的每一个数字配合线性基里的一部分数字都能异或出0,可是不同的0有多少个?我们不妨将线性基外的数字放入一个集合,这个集合的所有子集配合他们相应的能够异或出他们的线性基的数字就能异或出不同的0。而这个子集的个数很好求,2n-num个,n-num为线性基外的数字个数。
所以,我们要做的就是算出q-1前面有多少个数字,然后乘2n-num,再+1就是第一个q的位置。
我们不妨借用上面的程序,上面算出的是在不重复的集合中q的下标,那前面就是(下标-1)*2n-num+1就是答案了。
【AC代码】

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<set>
#include<climits>
#include<cstdlib>
#include<cmath>using namespace std;typedef long long ll;const int MAXN=100005;
const int MOD=10086;
int n,q,tmp;
ll quick_pow(ll a,ll b);    //用快速幂算2^n-num
struct L_B
{ll b[65],p[65];int cnt,flag;L_B(){memset(p,0,sizeof(p));memset(b,0,sizeof(b));cnt=flag=0;}void clear(){memset(p,0,sizeof(p));memset(b,0,sizeof(b));cnt=flag=0;}inline bool insert(ll x){for(int i=62;i>=0;--i)if(x&(1ll<<i)){if(b[i])x^=b[i];else{b[i]=x;return true;}}flag=1;return false;}ll get_max(){ll ret = 0;for(int i=62;i>=0;--i)if((ret^b[i])>ret)ret^=b[i];return ret;}ll get_max(ll initval){ll ret = initval;for(int i=62;i>=0;--i)if((ret^b[i])>ret)ret^=b[i];return ret;}ll get_min(){if(flag)return 0;for(int i=0;i<=62;++i)if(b[i])return b[i];return 0;}inline void rebuild(){for(int i=1;i<=62;++i)if(b[i])for(int j=0;j<i;++j)if(b[i]&(1ll<<j))b[i]^=b[j];for(int i=0;i<=62;++i)if(b[i])p[cnt++]=b[i];}ll kth(ll k){if(flag)--k;if(k==0)return 0;ll ret = 0;if(k>=(1ll<<cnt))return -1;for(int i=0;i<=cnt-1;++i)if(k&(1ll<<i))ret^=p[i];return ret;}int find_ans(int q){int num=0; int ans=0;vector<int> p;for(int i=0;i<=62;i++){if(b[i]){p.push_back(i);num++;}}for(int i=num-1;i>=0;i--){if(q>>p[i]&1){ans+=1<<i;}}//printf("test: ans=%d num=%d p[0]=%d\n",ans,num,p[0]);return (ans*quick_pow(2,n-num))%MOD+1;//ans本来是要+1再-1的,这里就省略了(我之前看其他博客他们好像都没有讲这个然后我就好久都不能理解,emmm,还是太菜了)}
};ll quick_pow(ll a,ll b)
{ll ret=1;while(b){if(b%2) ret=(ret*a)%MOD;a=a*a%MOD;b>>=1;}return ret;
}int main()
{L_B lis;int ans=0;scanf("%d",&n);for(int i=0;i<n;i++){scanf("%d",&tmp);lis.insert(tmp);}scanf("%d",&q);printf("%d",lis.find_ans(q)%MOD);//printf("%lld",quick_pow(2,5));return 0;
}

BZOJ 2844 | HYSBZ - 2844albus就是要第一个出场——线性基相关推荐

  1. 【BZOJ 2844】 albus就是要第一个出场

    2844: albus就是要第一个出场 Time Limit: 6 Sec  Memory Limit: 128 MB Submit: 436  Solved: 190 [Submit][Status ...

  2. 【bzoj 2844】: albus就是要第一个出场

    http://www.lydsy.com/JudgeOnline/problem.php?id=2844 先求线性基,那么可以得到0的个数cnt0 每个数与0异或都会得到2^cnt0这个数.... 那 ...

  3. 【BZOJ2844】albus就是要第一个出场——线性基

    Time Limit: 6 Sec Memory Limit: 128 MB Description 已知一个长度为n的正整数序列A(下标从1开始), 令 S = { x | 1 <= x &l ...

  4. BZOJ2844: albus就是要第一个出场(线性基)

    Time Limit: 6 Sec  Memory Limit: 128 MB Submit: 2054  Solved: 850 [Submit][Status][Discuss] Descript ...

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

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

  6. bzoj 4184 shallot 时间线建线段树+vector+线性基

    题目大意 n个时间点 每个时间点可以插入一个权值或删除一个权值 求每个时间点结束后异或最大值 分析 异或最大值用线性基 但是线性基并不支持删除操作 我们可以对时间线建一棵线段树 离线搞出每个权值出现的 ...

  7. bzoj 2844: albus就是要第一个出场 高斯消元

    LINK 题意:看题目不如看样例解释.给出有n个数的集合,对这些子集中的数求异或,升序统计所有子集得到的数(重复会被计入),询问一个数x,问这个数出现的第一个位置 思路:在这里要求一个所有可能出现的异 ...

  8. [BZOJ 2844] albus就是要第一个出场

    2844: albus就是要第一个出场 Time Limit: 6 Sec  Memory Limit: 128 MB Submit: 2316  Solved: 964 [Submit][Statu ...

  9. bzoj 2844 albus就是要第一个出场

    2844: albus就是要第一个出场 Time Limit: 6 Sec  Memory Limit: 128 MB Submit: 1402  Solved: 593 [Submit][Statu ...

最新文章

  1. 【CAD制图视频】AutoCAD 2014 高手之道
  2. python创_Python创建Windows 服务
  3. 【渝粤教育】电大中专电子商务网站建设与维护 (7)作业 题库
  4. LeetCode 12. Integer to Roman
  5. IIS 7 托管管道模式 经典模式(Classic) 集成模式(Integrated) 分析与理解
  6. linux搭建python运行环境_centos运行.py centos5.5下搭建python开发运行环境 - Linux - 服务器之家...
  7. 使用ZooKeeper实现分布式队列、分布式锁和选举详解
  8. JAVA内存的可见性
  9. 我的WCF之旅(1):创建一个简单的WCF程序(转载)
  10. bzoj 5281: [Usaco2018 Open]Talent Show【dp】
  11. Java毕设项目成都某4S店销售管理系统计算机(附源码+系统+数据库+LW)
  12. 工具分享-Windows 的绿色软件工具集
  13. docker安装mysql后无法执行mysql命令
  14. FutureMapping:空间人工智能的计算结构
  15. “蔚来杯“2022牛客暑期多校训练营5-A Don‘t Starve
  16. python画八卦图
  17. 微信小程序页面上面的名字怎么改_微信小程序名称可以修改几次? 微信小程序修改名称的方法...
  18. Apache POI读合并单元格
  19. Vue CLI 3结合Lerna进行UI框架设计
  20. linux关于日志文件介绍,Linux下重要日志文件介绍

热门文章

  1. Eclipse安装TestNG插件
  2. 如何查看Ubuntu版本,以及Linux内核版本??
  3. Qt中QTableWidget用法总结
  4. ADO.NET_09_Using 关键字
  5. PowerSocket对象与HostName
  6. pr文字转语音有插件吗_文字转语音软件深度解析
  7. 华为鸿蒙系统是否上线,华为官方:鸿蒙系统2.0上线,手机能否搭载鸿蒙操作系统?...
  8. tf 如何进行svd_Tensorflow快餐教程(6) - 矩阵分解
  9. python concat_python中merge、concat用法
  10. git服务器维护 备份,gitlab服务运维,备份与恢复 - 橙子柠檬's Blog