[关闭]
@lychee123 2017-08-13T17:19:45.000000Z 字数 1790 阅读 1172

HDU:6085 Rikka with Candies(ULL存数,位运算的应用)

位运算


HDU:6085 Rikka with Candies

题意:

组测试样例
个小朋友, 种糖果, 次询问(
接下来有 次输入表示第 个小朋友有 的钱()
接下来有 次输入表示第 种糖果为 的单价()
接下来 次询问,每次询问输入一个 表示询问第 个小朋友用自己的钱去买第 种单价糖果剩下的钱为 ,满足这种条件的()对数。如果答案为奇数输出 ,偶数则输出

样例:

Sample Input
1
5 5 5
1 2 3 4 5
1 2 3 4 5
0 1 2 3 4

Sample Output
0
0
0
0
1

分析:

  • 首先我们要知道 unsigned long long范围是[],而LL的范围是[,]
    题外话:遇到范围是,取模的这种限制条件时就要想到用unsigned long long类型。这样,如果ULL类型的整数溢出了,就相当于取模了。

  • 如果我们暴力的话复杂度为 显然会T。所以采用ULL和位运算结合使极限复杂度降到 ,但是每次操作的区间长度基本上都是远小于的,所以实际复杂度远小于这个值。

  • 思路:
    开一个二维数组a来存这个钱数是否存在过,如果存在过奇数次标记为1,偶数次标记为0;
    对于一个数x,0到x-1模上x的余数依次为0到x-1,所以直接将a的对应区间异或到ans的对应区间就可以离线处理出我们要的答案。最后对ans数组查找第x位。直接输出就OK!
    对于区间不为64整数倍,我们先将区间的r位置异或到ans的对应位置。然后不断减小r直到这个区间为64的整倍数。但是此时我们还会发现虽然此时已经是整倍数了,但并没有对齐块。此时将块往高位移动(往右)。直到移动到是整块的位置。此时a[w]则是a[0]往右移动w位的状态。将a[w]与ans异或起来就可以得出答案。

题目代码:

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. typedef unsigned long long ULL;
  4. const int maxn=50000+5;
  5. ULL a[65][800],ans[800];
  6. int b[maxn];
  7. void setbit(ULL a[],int pos)//对a[i]的第pos位进行反转
  8. {
  9. a[pos>>6]^=1ULL<<(pos&63);//a[pos/64]是分块 pos&63相当于对64取模
  10. }
  11. bool getbit(ULL a[],int pos)//查询对a[]的第pos位
  12. {
  13. return (a[pos>>6]>>(pos&63))&1ULL;
  14. }
  15. void getans(int l,int r)////将a[0]的[l,r)这个区间异或到ans的[0,r-l)区间
  16. {
  17. while((r-l)&63)//使区间是64整倍数
  18. {
  19. r--;
  20. if(getbit(a[0],r))
  21. setbit(ans,(r-l));
  22. }
  23. int w=0;
  24. while(l&63)
  25. {
  26. l++,r++,w++;
  27. }
  28. l=l>>6;
  29. r=r>>6;//找到对应的块
  30. for(int i=l;i<r;i++)
  31. {
  32. ans[i-l]^=a[w][i];
  33. }
  34. }
  35. int main()
  36. {
  37. int T;
  38. scanf("%d",&T);
  39. while(T--)
  40. {
  41. memset(a,0,sizeof(a));
  42. memset(b,0,sizeof(b));
  43. memset(ans,0,sizeof(ans));
  44. int n,m,q;
  45. scanf("%d%d%d",&n,&m,&q);
  46. while(n--)
  47. {
  48. int x;
  49. scanf("%d",&x);
  50. for(int i=0;i<64;i++)
  51. setbit(a[i],x+i);//将a[x]表示将a[0]往高位移动x位
  52. }
  53. while(m--)
  54. {
  55. int x;
  56. scanf("%d",&x);
  57. b[x]=1;
  58. }
  59. for(int i=0;i<maxn;i++)
  60. {
  61. if(b[i])
  62. {
  63. for(int j=0;j<maxn;j+=i)
  64. getans(j,min(j+i,maxn));
  65. }
  66. }
  67. while(q--)
  68. {
  69. int x;
  70. scanf("%d",&x);
  71. printf("%d\n",(int)getbit(ans,x));
  72. }
  73. }
  74. return 0;
  75. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注