1 条题解
-
0
自动搬运
来自洛谷,原作者为

Alex_Wei
**搬运于
2025-08-24 22:32:39,当前版本为作者最后更新于2021-07-28 16:14:48,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
题意简述:给出 个 位二进制数(随机生成)。对于 个询问,每次给出一个 位二进制数 和一个十进制数 ,求是否存在 使得 不同位数个数不大于 。
注意到这个 ,一定是本题的突破点。再根据 与抽屉原理,不难想到将 位的二进制数看成 位的 进制数。这样一来,如果 与 在二进制下不同位数个数不大于 ,那么它们在 进制下必定至少有一位完全相等。这是显然的。
因此,我们可以枚举 在 进制下的 位,并检查与 在该位相等的所有 是否符合要求。由于数据随机生成,所以某一位为某个数的 的期望个数为 。所以对于每一位,我们期望检查 个 是否符合要求。而满足在 进制下第 位为 的 的所有 可以开
vector存储。检查方法很简单:要求出 进制数 在二进制下有多少位不同,只需要预处理出 在二进制下 的个数,然后枚举 的每一位(一共 位),加上 它们在这一位的值的异或和 在二进制下 的个数即可。
极限数据下空间复杂度为 ,期望时间复杂度为 ,其中 表示询问个数,第一个 表示枚举的 位, 表示与 在枚举的某一位的值相等的 的期望个数,而第二个 表示检查的复杂度。
为了卡常,可以进行以下优化:
- 把
vector换成链式前向星。 - 使用
fread。 - 检查时使用指针而不是数组。
- 如果已经不符合条件,退出检查(不加这个优化会 T 掉几个点)。
#include <bits/stdc++.h> using namespace std; #define gc getchar() #define mem(x,v) memset(x,v,sizeof(x)) typedef unsigned long long ull; typedef unsigned short us; namespace IO{ char buf[1<<23],*p1=buf,*p2=buf; #ifdef __WIN32 #define gc getchar() #else #define gc (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<22,stdin),p1==p2)?EOF:*p1++) #endif inline int read(){ int x=0;char s=gc; while(!isdigit(s))s=gc; while(isdigit(s))x=(x<<1)+(x<<3)+(s-'0'),s=gc; return x; } } using namespace IO; const int N=400000+5; const int W=65536; bool s[N][256],q[256]; ull myRand(ull &k1,ull &k2){ ull k3=k1,k4=k2; k1=k4,k3^=(k3<<23),k2=k3^k4^(k3>>17)^(k4>>26); return k2+k4; } void gen(int n,ull a1,ull a2){ for(int i=0;i<n;i++) for(int j=0;j<256;j++) s[i][j]=(myRand(a1,a2)&(1ull<<32))?1:0; } struct EDGE{ int cnt,hd[W],nxt[N],to[N]; void add(int x,int y){nxt[++cnt]=hd[x],hd[x]=cnt,to[cnt]=y;} }buc[16]; ull n,m,a1,a2; us val[N][16],mp[W],qq[16]; int main(){ cin>>n>>m>>a1>>a2,gen(n,a1,a2); for(int i=0;i<n;i++) for(int j=0;j<16;j++){ for(int k=0;k<16;k++) val[i][j]+=s[i][j*16+k]<<k; buc[j].add(val[i][j],i); } for(int i=1;i<W;i++)mp[i]=mp[i>>1]+(i&1); for(int i=0,las=0,k;i<m;i++,mem(qq,0)){ for(int j=0,vv=0;j<64;j++,vv=0){ char s=gc; if(isdigit(s))vv=s-'0'; else if(s>='A'&&s<='F')vv=10+s-'A'; else {j--; continue;} for(int l=0;l<4;l++)q[j*4+l]=(vv>>3-l)&1; } bool ok=0; k=read(); for(int j=0;j<16;j++) for(int l=0;l<16;l++) qq[j]+=(q[j*16+l]^las)<<l; for(int j=0;j<16;j++){ for(int p=buc[j].hd[qq[j]];p;p=buc[j].nxt[p]){ int it=buc[j].to[p],cnt=0; us *pval=val[it],*pq=qq; for(int l=0;l<16;l++,pval++,pq++){ cnt+=mp[(*pval)^(*pq)]; if(cnt>k)break; } if(cnt<=k){ok=1; break;} } if(ok)break; } cout<<(las=ok)<<'\n'; } return 0; } - 把
- 1
信息
- ID
- 7114
- 时间
- 2500ms
- 内存
- 384MiB
- 难度
- 6
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者