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

Mingoal
这个家伙很懒,随便留下了一句话搬运于
2025-08-24 21:40:51,当前版本为作者最后更新于2018-01-21 14:07:17,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
我发一个0ms的代码。
我的思想是枚举长度,把二进制字符串压位,然后累加
详见注释:
#include<bits/stdc++.h> using namespace std; const int N=4096; struct kk{ int x,y,z; }b[500000]; int A,B,n,m,s[200003],v[N],k,c[13],i,j,t,cnt,to,k1; char ch; int cmp(kk x,kk y){ return x.x>y.x || x.x==y.x && (x.z<y.z || x.z==y.z && x.y<y.y); } void chan(int x,int y){//把十进制x转成二进制,y表示二进制位数 int tot=0; while (x){ c[tot++]=x%2; x/=2; } for (int i=0;i<=y-tot;i++) putchar(48);//位数不够用0补 for (int i=tot-1;i>=0;i--) putchar(c[i]|48); } int main(){ cin>>A>>B>>n; while ((ch=getchar())!=EOF) if (ch==48 || ch==49) s[m++]=ch^48;//读入,把'0'和'1'变成0和1,位运算更快 B=min(B,m);//最长也不能超过总长度 for (i=0;i<B;i++){ k=k<<1|s[i];//k记录0..i-1位的序列,k<<1|1相当于k*2+1,但这样更快 if (i>=A-1){ t=(1<<i+1)-1; memset(v,0,sizeof(v)); v[k]++; k1=k; for (j=i+1;j<m;j++){ k1=(k1<<1|s[j])&t;//这里是取k的二进制后i+1位 %(2^(i+1))相当于&(2^(i+1)-1),常用技巧,不懂的话下面有解释 v[k1]++;//记录 } for (j=0;j<=t;j++) if (v[j]) b[cnt].x=v[j],b[cnt].y=j,b[cnt++].z=i;//x记录频率,y记录值,z记录长度 } } sort(b,b+cnt,cmp); j=0; for (i=0;i<n && j<cnt;i++){ printf("%d\n",b[j].x); to=1; while (b[j+1].x==b[j].x){ chan(b[j].y,b[j].z); j++; if (to==6) putchar('\n'),to=0;//没6个换1行 else putchar(' '); to++; } chan(b[j].y,b[j].z); j++; if (to) putchar('\n'); } }其实代码中还有一些地方可以优化,但是我已经0ms了,也没继续优化
这里说一下为什么当k=2^t时x%k=x&(k-1)
x%k相当于取x二进制末t位
k-1的二进制就是t个1
x末t位0还是0,1还是1,不变
x前面的几位不管是0还是1,因为k的对应位是0,所以也变成0
- 1
信息
- ID
- 1754
- 时间
- 1000ms
- 内存
- 125MiB
- 难度
- 5
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者