洛谷 P2724 联系 Contact
特坑题
题意
给你一个字符串(会有换行),求出在长度A~B的01字符串出现最多的N种(出现次数一样多的算一种),输出它的次数以及分别是哪些字符串,出现次数为第一关键字,字符串的长度为第二关键字,字符串的大小(也就是二进制化为整数的大小)为第三关键字。
做法
第一眼看时觉得挺水,感觉只有普及+左右的难度,就是普通的暴力枚举,但是用DFS会超时,所以要用一些技巧,也就是位运算的技巧,把二进制强压成十进制数,就不用一位一位的比较了,再用结构体sort排序,在输出就行。
坑点
1.枚举的时间复杂度是关键,如果你不信,可以用暴力枚举尝试(第五个点和第七个点会让你怀疑人生);
2.输入时的换行;
3.输出是的每六个一行以及末尾不能有空格(六个一行时要注意:当接下来没有答案时,不能换行(本人卡这多时));
#include<bits/stdc++.h> using namespace std; int A,B,N; char s[200010]; int ans=0;//记录出现过的二进制数的个数(因为要排除未出现的) int n; struct t { int len, value, cnt; }pinlu[20010];//len是二进制数的长度,value是二进制化十进制的结果,cnt是出现次数 bool cmp(t x,t y) { if(x.cnt==y.cnt) { if(x.len==y.len) return x.value < y.value; return x.len < y.len; } return x.cnt > y.cnt; } void print(int l, int v) { for (int i = l-1; i >= 0; --i) putchar('0'+ ((v>>i)&1));//将十进制化为二进制后输出 } int main() { cin>>A>>B>>N; while (true) { char ch = getchar(); if (ch == EOF) break; if (ch == '0' || ch == '1') s[++n] = ch; } int ans=0; for(int m=A;m<=B;++m) { int cnt[1<<12]={}; int sum=0; for(int i=1;i<=m;++i) sum*=2,sum+=s[i]-'0';//二进制十进制 for(int i=m;i<=n;++i) { cnt[sum]++; if(s[i-m+1] == '1') sum-=(1<<(m-1)); sum*=2; sum+=s[i+1]-'0';//技巧计算 } for(int i=0;i<(1<<m);++i) if(cnt[i]) pinlu[++ans].len=m,pinlu[ans].cnt=cnt[i],pinlu[ans].value=i; } sort(pinlu+1,pinlu+ans+1,cmp);//排序 int ss=0;//ss记录种类数 int now=0;//now记录当前轮到的二进制数 while(ss<N&&now<ans) { ++ss; ++now; if(ss!=1) cout<<endl;//在第一次的输出后换行 cout<<pinlu[now].cnt<<endl;//输出种类数 print(pinlu[now].len,pinlu[now].value); int lh=1;//后面的换行记录 for(int i=now+1;i<=ans;++i) { if(pinlu[i].cnt==pinlu[now].cnt)//判断出现次数是否相等 { if(lh%6!=0) cout<<" "; print(pinlu[i].len, pinlu[i].value); ++now; ++lh; if(lh%6==0&&pinlu[i+1].cnt==pinlu[now].cnt) cout<<endl;//每六个换行,判断是否有“第七者” } else break;//如果没有找到就跳出 } } cout<<endl; return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】