• USACO 3.1 联系


    这题巨多坑点啊,就算算法对了也D了半个小时orz

    看到题目,我的想法是记录每种串的出现次数,将串转成二进制计算值即可。由于010和0010可能被重复计在一起,所以要限制长度k

    所以,用cnt[k][i]表示长度为k,值为i的串的出现次数

    但稍等!如果我们每个串都计算一次,那么是会超时的,这里就要用到一个技巧:滚动哈希

    考虑一个串110110101,长度为3,现在我们算出了110的哈希值为5,那么怎么算下一位101的值呢?

    稍加分析即可发现,我们将110向左移一位变成1100,现在我们得去掉最高位的1,就将它& ((1<<k) - 1)(即为0111,这样就除去了超过三位的数字),再将它或目前的值,就能O(1)得到当前哈希值

    这样,复杂度就为O(nb),可以通过本题

    但这道题的坑点不在此,而是输出和特判!!

    输出的换行和细节具体见代码,还有就是如果a > b直接return 0 ,如果b > len,那么将b变为len即可,见代码

    以上
    时间:2.0h

    
    

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<climits>
    #include<queue>
    using namespace std;
    const int maxn = 2e5 + 5;
    inline int read()
    {
    int ans = 0,op = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9')
    {
    if(ch == '-') op = -1;
    ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
    (ans *= 10) += ch - '0';
    ch = getchar();
    }
    return ans * op;
    }
    int aa,b,n;
    int cnt[13][1 << 12];
    char s[maxn];
    char ss[110];
    int a[maxn];
    int invert(int s,int e)
    {
    int ans = 0;
    for(int i = s;i <= e;i++)
    {
    (ans += a[i]) *= 2;
    //cout << a[i];
    }
    return ans >> 1;
    }
    int ans[20];
    void rebuild(int k,int len)
    {
    int temp = len;
    memset(ans,0,sizeof(ans));
    while(len--)
    {
    ans[len] = k & 1;
    k = k >> 1;
    }
    for(int i = 0;i < temp;i++) printf("%d",ans[i]);
    }
    struct node
    {
    int v,len,tv;
    bool operator < (const node& a) const
    {
    if(v != a.v) return v > a.v;
    else if(len != a.len) return len < a.len;
    else return tv < a.tv;
    }
    }st[maxn];
    int top;
    int len;
    int main()
    {
    aa = read(),b = read(),n = read();
    while(scanf("%s",ss + 1) != EOF)
    {
    for(int i = 1;i <= strlen(ss + 1);i++)
    {
    len++;
    s[len] = ss[i];
    }
    }
    b = min(b,len);
    if(aa > b) return 0;
    for(int i = 1;i <= len;i++) a[i] = s[i] - '0';
    for(int k = aa;k <= b;k++)
    {
    int temp = invert(1,1 + k - 1);
    cnt[k][temp]++;
    for(int i = k + 1;i <= len;i++)
    {
    temp = ((temp << 1) & ((1 << k) - 1)) | a[i];
    cnt[k][temp]++;
    }
    }
    for(int k = aa;k <= b;k++)
    for(int i = 0;i <= (1 << k) - 1;i++)
    if(cnt[k][i]) st[++top].v = cnt[k][i],st[top].len = k,st[top].tv = i;
    sort(st + 1,st + 1 + top);
    int j = 1;
    for(int i = 1;i <= n;i++)
    {
    if(j > top) break;
    printf("%d ",st[j].v);
    int tot = 1;
    rebuild(st[j].tv,st[j].len);
    printf(" ");
    while(st[j].v == st[j + 1].v && j + 1 <= top)
    {
    j++;
    rebuild(st[j].tv,st[j].len);
    tot++;
    printf(" ");
    if(tot >= 6) { printf(" "); tot = 0; }
    }
    j++;
    if(tot) printf(" ");
    }
    //cout << endl;
    }

     
  • 相关阅读:
    再读《赤壁赋》念《滕王阁序》
    赤壁赋
    关于C语言中的位域
    Eliot
    cnblogs.com博客园简介
    springboot+thymeleaf 实现图片文件上传及回显
    绑定事件的方式
    无法获得 VMCI 驱动程序的版本: 句柄无效。
    Connection is read-only解决方式
    Java 线程的 5 种状态
  • 原文地址:https://www.cnblogs.com/LM-LBG/p/10022213.html
Copyright © 2020-2023  润新知