HDU 6085 Rikka with Candies (暴力压位)

来源:互联网 发布:钉钉 阿里云企业邮箱 编辑:程序博客网 时间:2024/06/06 09:14

题目链接

HDU 6085 Rikka with Candies

分析

其实很容易想到一个有技巧的暴力方法,我们可以这样办

首先对于每一个 Ai 我们考虑比 Ai 大的部分 B ,对于这部分 B,Ai%B=Ai ,所以我们通过计算前缀和可以在 O(1) 计算出这部分值,因此我们先不考虑这部分值,

对于比 Ai 小的部分 B 我们反过来对每个 Bi 考虑比 Bi 大的部分 A,那么对于每个 Bi,Ai 的贡献一定是 [0,1,2,Bi1] 的循环,即 A,[Bi,maxAi] 这一部分的贡献恰好是循环 [0,1,2,Bi1] ,如果我们把 Ai 处理成

a[i] : 用01表示值为i的数存在与否,b[i]同理

则对于每个 Bi 我们只需将 a[kBi,(k+1)Bi1] 这一部分加到答案 ans[0,1,2,Bi1] ,暴力是 O(nm) 如果我们将 a 压位就可以在 O(nm/32) 得出结果.具体压位可见代码

AC code

// Problem : 6085 ( Rikka with Candies )     Judge Status : Accepted// RunId : 21600845    Language : G++    Author : zouzhitao// Code Render Status : Rendered By HDOJ G++ Code Render Version 0.01 Beta#include<bits/stdc++.h>#define pb push_back#define mp make_pair#define PI acos(-1)#define fi first#define se second#define INF 0x3f3f3f3f#define INF64 0x3f3f3f3f3f3f3f3f#define random(a,b) ((a)+rand()%((b)-(a)+1))#define ms(x,v) memset((x),(v),sizeof(x))#define scint(x)  scanf("%d",&x );using namespace std;const int MOD = 1e9+7;const double eps = 1e-8;typedef long long LL;typedef long double DB;typedef pair<int,int> PII;const int maxn = 5e4 +10;LL ans[maxn];LL bit_ans[maxn];int a[maxn],b[maxn];LL digit[maxn][35];LL sum[maxn];int maxa,maxb;void add(int idx,int l){   //重idx开始+l位到bit_ans;   int L = 0 , R = min(maxa-idx,l-1);   while (L<=R) {      int d = L/32;      if(idx+L>maxa)break;      if(R-L>=31){         bit_ans[d] ^=digit[idx+L][32];         L+=32;      }else{         bit_ans[d] ^=digit[idx+L][R-L+1];         L=R+1;      }      // std::cout << L<<" LR "<<R << "d = "<<d <<"idx="<<idx <<'\n';      // std::cout << bitset<64>(bit_ans[d]) << '\n';   }}int main(int argc, char const *argv[]) {   int T;   scanf("%d",&T );   while (T--) {      maxa = 0;      maxb = 0;      int n,m,k;      scanf("%d%d%d",&n,&m,&k );      ms(a,0);ms(b,0);ms(ans,0);      ms(digit,0);ms(sum,0);      ms(bit_ans,0);      for(int i=0 ; i<n ; ++i){         int x;scanf("%d",&x );         a[x] =1;         maxa = max(x,maxa);      }      for(int i=0 ; i<m ; ++i){         int x;scint(x);         b[x]=1;         maxb = max(maxb,x);      }      //压位      for(int i=1 ; i<=maxa ; ++i){         LL bit =0;         // std::cout << i<<" " <<a[i] << '\n';         for(int j =0 ; j<32&&(i+j)<=maxa ; ++j){            bit <<=1;bit |=a[i+j];//从i开始长度为j+1的位            digit[i][j+1] = bit<<(31-j);            // std::cout << bitset<64>(digit[i][j+1]) << '\n';         }      }      for(int i=1 ; i<=maxb ; ++i){         if(b[i]){            // std::cout << i<<" bi "<<b[i] << '\n';            for(int j=i ; j<=maxa ;j+=i ){               add(j,i);            }         }      }      for(int i=0 ; i*32 <=5e4 ; ++i){         int j = (i+1) * 32 -1;         int t =32;         while (t--) {            ans[j] = bit_ans[i]&1;j--;bit_ans[i]>>=1;         }      }      sum[0] =0;      for(int i=1 ; i<=maxb ; ++i){         sum[i] = sum[i-1] + b[i];      }      for(int i=1 ; i<=maxa ; ++i){         if(a[i]){            ans[i]^= (sum[maxb]-sum[i])&1;         }      }      while (k--) {         int x;scint(x);         printf("%d\n",ans[x] );      }   }   return 0;}