【HDU3949】XOR

【题目大意】

给定一个数组,求这些数组通过异或能得到的数中的第k小是多少。

传送门:http://vjudge.net/problem/HDU-3949

【题解】

首先高斯消元求出线性基,然后将k按照二进制拆分即可。

注意当高斯消元结束后若末尾有0则第1小是0 特判一下然后k--。

然后HDU输出long long是用%I64d 无论C++还是G++都是。(虽然我用了lld也AC了)

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cstdlib>
 5 #include<ctime>
 6 #include<cmath>
 7 #include<algorithm>
 8 using namespace std;
 9 typedef long long ll;
10 #define MAXN 10010
11 ll T,n,m,flag,a[MAXN];
12 inline ll read()
13 {
14     ll x=0,f=1;  char ch=getchar();
15     while(!isdigit(ch))  {if(ch==‘-‘)  f=-1;  ch=getchar();}
16     while(isdigit(ch))  {x=x*10+ch-‘0‘;  ch=getchar();}
17     return x*f;
18 }
19 void guess()
20 {
21     ll temp=0;
22     for(ll i=(1ll<<62),j;i;i>>=1)
23     {
24         for(j=temp+1;j<=n;j++)  if(a[j]&i)  break;
25         if(j>n)  continue;
26         swap(a[++temp],a[j]);
27         for(ll j=1;j<=n;j++)  if(j!=temp&&(a[j]&i))  a[j]^=a[temp];
28     }
29     flag=(temp!=n);
30     n=temp;
31 }
32 ll ask(ll x)
33 {
34     x-=flag;  ll ans=0;
35     if(!x)  return 0;
36     for(int i=n;i;i--)  {if(x&1)  ans^=a[i];  x>>=1;}
37     if(x)  return -1;
38     return ans;
39 }
40 int main()
41 {
42     //freopen("cin.in","r",stdin);
43     //freopen("cout.out","w",stdout);
44     T=read();
45     for(int CASE=1;CASE<=T;CASE++)
46     {
47         printf("Case #%d:\n",CASE);
48         n=read();
49         for(int i=1;i<=n;i++)  a[i]=read();
50         guess();
51         m=read();
52         for(int i=1;i<=m;i++)  {ll x=read();  printf("%I64d\n",ask(x));}
53     }
54     return 0;
55 }

附上makedata程序:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<ctime>
 4 #include<cstdlib>
 5 using namespace std;
 6 int main()
 7 {
 8     freopen("cin.in","w",stdout);
 9     srand(time(NULL));
10     int T=30;
11     printf("%d\n",T);
12     while(T--)
13     {
14         int n=10000;  printf("%d\n",n);
15         for(int i=1;i<=n;i++)  printf("%I64d ",(long long)rand()*rand()*rand());
16         int m=10000;  printf("\n%d\n",m);
17         for(int i=1;i<=m;i++)  printf("%d ",rand()%n+1);
18         printf("\n");
19     }
20     return 0;
21 }
时间: 2024-08-10 13:18:00

【HDU3949】XOR的相关文章

【HDU3949】XOR 线性基

#include <stdio.h> int main() { puts("转载请注明出处谢谢"); puts("http://blog.csdn.net/vmurder/article/details/43448493"); } 题意:给若干个数让你异或,然后询问第k大的异或和. 题解: 先搞出来线性基,然后第k大的异或和就是: 把k二进制拆分,第i位上有1,就把第i个线性基异或进来. 原因: 因为线性基是一堆高位上的1(或许有一些位动不了),然后把这

【BZOJ2337】Xor和路径(高斯消元)

[BZOJ2337]Xor和路径(高斯消元) 题面 BZOJ 题解 我应该多学点套路: 对于xor之类的位运算,要想到每一位拆开算贡献 所以,对于每一位拆开来看 好了,既然是按位来算 我们就只需要计算从\(1\)号点开始 到\(n\)的路径中,路径的异或和为\(1\)的概率 显然没法算 还是一样的 考虑高斯消元 对于每一个节点\(i\) \[f[i]=\sum_{w(u,i)=1}\frac{1-f[u]}{op[u]}+\sum_{w(u,i)=1}\frac{f[u]}{op[u]}\] 其

【bzoj2115】 Xor

www.lydsy.com/JudgeOnline/problem.php?id=2115 (题目链接) 题意:给出一张图,可能有重边和自环,在图中找出一条从1-n的路径,使得经过的路径的权值的异或和最大,每条边可以重复经过并且重复计算异或和. Solution  刚看到这道题,想了10分钟完全没有思路,于是就膜了题解.  我们先把图看成一棵树,那么我们所需要找出的路径可以分成一些环和一条从1-n的树上路径,至于树是怎么构造的以及那条从1-n的路径是怎么走的并不重要,因为我们可以通过在总路径上补

bzoj2115【WC2001】Xor

2115: [Wc2011] Xor Time Limit: 10 Sec  Memory Limit: 259 MB Submit: 2059  Solved: 856 [Submit][Status][Discuss] Description Input 第一行包括两个整数N和 M, 表示该无向图中点的数目与边的数目. 接下来M 行描写叙述 M 条边,每行三个整数Si.Ti ,Di,表示 Si 与Ti之间存在 一条权值为 Di的无向边. 图中可能有重边或自环. Output 仅包括一个整数,

【BZOJ-2115】Xor 线性基 + DFS

2115: [Wc2011] Xor Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 2142  Solved: 893[Submit][Status][Discuss] Description Input 第一行包含两个整数N和 M, 表示该无向图中点的数目与边的数目. 接下来M 行描述 M 条边,每行三个整数Si,Ti ,Di,表示 Si 与Ti之间存在 一条权值为 Di的无向边. 图中可能有重边或自环. Output 仅包含一个整数,表示最大

【HNOI2011】XOR和路径

pre.cjk { font-family: "Droid Sans Fallback", monospace } p { margin-bottom: 0.25cm; line-height: 120% } a:link { } 和期望有关的题一脸懵逼QAQ 题目要求的是异或和的期望,所以就把二进制的每一位都搞一遍,最后答案就是每一位的期望和. 然后对于每一位,推出一个很鬼畜的DP方程:f[i]表示i这个点到n的概率. f[n][n]=1;然后枚举i,枚举i连的每个点,如果这条路的边

【BZOJ2115】【Wc2011】 Xor 线性基 异或最长路

#include <stdio.h> int main() { puts("转载请注明出处谢谢"); puts("http://blog.csdn.net/vmurder/article/details/43410545"); } 题意:找一条异或最长路. 题解:先随便来一条路径,然后我们发现这条路径上可以随便加简单环(不管有没有共点共边). 就是因为可以先从某点走到环上来一圈再走回来,这样来去的路径被搞没了,简直污得不行. 然后我们可以用线性基来决定去

【Hdu4825】Xor Sum(01字典树)

Description Zeus 和 Prometheus 做了一个游戏,Prometheus 给 Zeus 一个集合,集合中包含了N个正整数,随后 Prometheus 将向 Zeus 发起M次询问,每次询问中包含一个正整数 S ,之后 Zeus 需要在集合当中找出一个正整数 K ,使得 K 与 S 的异或结果最大.Prometheus 为了让 Zeus 看到人类的伟大,随即同意 Zeus 可以向人类求助.你能证明人类的智慧么? Solution 01字典树入门题 Code #include

【BZOJ】2337: [HNOI2011]XOR和路径

[算法]期望+高斯消元 [题解]因为异或不能和期望同时运算,所以必须转为加乘 考虑拆位,那么对于边权为1取反,边权为0不变. E(x)表示从x出发到n的路径xor期望. 对于点x,有E(x)=Σ(1-E(y))(边权1)||E(y)(边权0)/t[x]  t[x]为x的度. 那么有n个方程,整体乘上t[x]确保精度,右项E(x)移到左边--方程可以各种变形. 每次计算完后*(1<<k)就是贡献. 逆推的原因在于n不能重复经过,而1能重复经过,所以如果计算"来源"不能计算n,