BZOJ_2795_[Poi2012]A Horrible Poem_hash+暴力

Description

给出一个由小写英文字母组成的字符串S,再给出q个询问,要求回答S某个子串的最短循环节。
如果字符串B是字符串A的循环节,那么A可以由B重复若干次得到。

Input

第一行一个正整数n (n<=500,000),表示S的长度。
第二行n个小写英文字母,表示字符串S。
第三行一个正整数q (q<=2,000,000),表示询问个数。
下面q行每行两个正整数a,b (1<=a<=b<=n),表示询问字符串S[a..b]的最短循环节长度。

Output

依次输出q行正整数,第i行的正整数对应第i个询问的答案。

Sample Input

8
aaabcabc
3
1 3
3 8
4 8

Sample Output

1
3
5


正解:http://www.cnblogs.com/Winniechen/p/9042992.html

我们现在要求[L,R]的最短循环节,假设长度为x。

那么满足[L+x,R]和[L,R-x]两个子串是相等的,这一步可以用hash解决。

随机询问n次某个数的约数个数这个是期望$O(nln)$的,上限是$O(n\sqrt n)$。

所以我们先把每个数的约数处理出来,存到vector中,这一步也是$O(nln)$的。

询问时暴力枚举约数即可。

然后hash用unsigned int自然溢出,卡一卡就过了。

代码:

// luogu-judger-enable-o2
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <vector>
using namespace std;
#define N 500050
#define RR register
__attribute__((optimize("-O2")))inline char nc() {
    static char buf[100000],*p1,*p2;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
__attribute__((optimize("-O2")))inline int rd() {
    RR int x=0;RR char c=nc();
    while(c<‘0‘||c>‘9‘) c=nc();
    while(c>=‘0‘&&c<=‘9‘) x=(x<<3)+(x<<1)+c-‘0‘,c=nc();
    return x;
}
__attribute__((optimize("-O2")))inline int rc() {
    RR char c=nc();
    while(c<‘a‘||c>‘z‘) c=nc();
    return (int)c;
}
typedef unsigned int ll;
int n,m;
int s[N];
ll h[N],mi[N],base=19260817;
vector<int>q[N];
__attribute__((optimize("-O2")))inline ll get_hash(int l,int r) {
    return h[r]-h[l-1]*mi[r-l+1];
}
__attribute__((optimize("-O2")))inline int solve(int l,int r) {
    int len=r-l+1,i;
    int siz=q[len].size();
    for(i=0;i<siz;i++) {
        int x=q[len][i];
        if(get_hash(l+x,r)==get_hash(l,r-x)) return x;
    }
}
char pbuf[10000000] , *pp = pbuf;
inline void write(int x)
{
    static int sta[20];
    RR int top = 0;
    if(!x)sta[++top]=0;
    while(x) sta[++top] = x % 10 , x /= 10;
    while(top) *pp ++ = sta[top -- ] ^ ‘0‘;
}
__attribute__((optimize("-O2")))int main() {
    RR int i,x,y,j;
    n=rd();
    for(i=1;i<=n;i++) s[i]=rc();
    m=rd();
    for(mi[0]=1,i=1;i<=n;i++) {
        h[i]=h[i-1]*base+s[i];
        mi[i]=mi[i-1]*base;
    }
    for(i=1;i<=n;i++) {
        for(j=i;j<=n;j+=i) {
            q[j].push_back(i);
        }
    }
    while(m--) {
        x=rd(); y=rd();
        write(solve(x,y));*pp ++ =‘\n‘;
    }
    fwrite(pbuf , 1 , pp - pbuf , stdout);
}
/*
8
aaabcabc
3
1 3
3 8
4 8
*/

原文地址:https://www.cnblogs.com/suika/p/9062452.html

时间: 2024-10-02 22:01:58

BZOJ_2795_[Poi2012]A Horrible Poem_hash+暴力的相关文章

[BZOJ2795][Poi2012]A Horrible Poem

2795: [Poi2012]A Horrible Poem Time Limit: 50 Sec  Memory Limit: 128 MBSubmit: 261  Solved: 150[Submit][Status][Discuss] Description 给出一个由小写英文字母组成的字符串S,再给出q个询问,要求回答S某个子串的最短循环节.如果字符串B是字符串A的循环节,那么A可以由B重复若干次得到. Input 第一行一个正整数n (n<=500,000),表示S的长度.第二行n个小

2795: [Poi2012]A Horrible Poem

2795: [Poi2012]A Horrible Poem Time Limit: 50 Sec  Memory Limit: 128 MBSubmit: 484  Solved: 235[Submit][Status][Discuss] Description 给出一个由小写英文字母组成的字符串S,再给出q个询问,要求回答S某个子串的最短循环节.如果字符串B是字符串A的循环节,那么A可以由B重复若干次得到. Input 第一行一个正整数n (n<=500,000),表示S的长度.第二行n个小

【BZOJ2795】[Poi2012]A Horrible Poem hash

[BZOJ2795][Poi2012]A Horrible Poem Description 给出一个由小写英文字母组成的字符串S,再给出q个询问,要求回答S某个子串的最短循环节.如果字符串B是字符串A的循环节,那么A可以由B重复若干次得到. Input 第一行一个正整数n (n<=500,000),表示S的长度.第二行n个小写英文字母,表示字符串S.第三行一个正整数q (q<=2,000,000),表示询问个数.下面q行每行两个正整数a,b (1<=a<=b<=n),表示询

BZOJ 2795: [Poi2012]A Horrible Poem( hash )

...字符串hash. #include<bits/stdc++.h> using namespace std; typedef unsigned long long ull; const int maxn = 500009; const ull P = 1000173169; char S[maxn]; int check[maxn], prime[maxn], N = 0, n; ull H[maxn], K[maxn]; void init() { memset(check, 0, si

【bzoj2795】[Poi2012]A Horrible Poem Hash+分解质因数

题目描述 给出一个由小写英文字母组成的字符串S,再给出q个询问,要求回答S某个子串的最短循环节.如果字符串B是字符串A的循环节,那么A可以由B重复若干次得到. 输入 第一行一个正整数n (n<=500,000),表示S的长度.第二行n个小写英文字母,表示字符串S.第三行一个正整数q (q<=2,000,000),表示询问个数.下面q行每行两个正整数a,b (1<=a<=b<=n),表示询问字符串S[a..b]的最短循环节长度. 输出 依次输出q行正整数,第i行的正整数对应第i

[Poi2012]A Horrible Poem

先放个简单版的 Pku2406 Power Strings Given two strings a and b we define a*b to be their concatenation. For example, if a = "abc" and b = "def" then a*b = "abcdef". If we think of concatenation as multiplication, exponentiation by a

【醒目】【业界偷懒】【Public】BZOJ题目一句话题解整理

就当是复习一下自己做过的题,顺便提供一个简要题解给大家看. 做题时候实在想不出来看一下一句话题解,可以有一个提示的作用又不至于一下子知道了全部浪费了一道题吧.. 部分题目(如我A过得大部分奶牛题)是别人拿我的账号做的,不提供题解. 可能会漏掉很多做过的题..因为可能点页数不小心点错了什么的 UPD.本来想把那些没写过但是知道题解的也写了..但是写完这些已经累死了QAQ 已AC的题目(数学题均不提供分析过程,公式): 1000:A+B 1001:平面图最小割,转对偶图最短路 1002:矩阵树定理,

【bzoj2793】[Poi2012]Vouchers 暴力

题目描述 考虑正整数集合,现在有n组人依次来取数,假设第i组来了x人,他们每个取的数一定是x的倍数,并且是还剩下的最小的x个.正整数中有m个数被标成了幸运数,问有哪些人取到了幸运数. 输入 第一行一个正整数m (m<=1,000,000),下面m行每行一个正整数x (x<=1,000,000),表示x是一个幸运数.接下来一行一个正整数n (n<=1,000,000),下面n行每行一个正整数x (x<=1,000,000),表示这一组来了x个人. 输出 第一行输出一个非负整数k,表示

【bzoj2795】【Poi2012】A Horrible Poem

题解: 询问区间的整循环节 设区间长度为$n$ 如果有循环节长为$x$和$y$,那由斐蜀定理得$gcd(x,y)$也一定为一个循环节: 假设最小的循环节长为$mn$,那么对于任何循环节长$x$,一定$mn | x$ , 否则$gcd(mn,x)<mn$矛盾 推出$\frac{n}{x} | \frac{n}{mn}$ 所以每次提出$n$的一个质因子$p$,考虑是否可以分成$p$段,如果可以$n=\frac{n}{p}$继续找: 最后得出来的$n$就是最短的循环节: 分解质因子可以$O(n)$线筛