洛谷 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;
}
复制代码

 

posted @   LikC1606  阅读(27)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示