这题巨多坑点啊,就算算法对了也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\n",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("\n"); tot = 0; } } j++; if(tot) printf("\n"); } //cout << endl;}