bzoj2795

循环节的经典性质

n是[l,r]这一段的循环节的充要条件是[l,r-n]和[l+n,r]相同 且n是长度的约数

然后不难想到根号的穷举约数的做法

有没有更好的做法,我们知道如果n是一个循环节,那么k*n也必定是一个循环节

我们只要穷举质因子,不断除以原长并保证其仍是循环节,直到不能再小为止即可

穷举质因子我们可以记录每个数的最小质因数(显然可以用线性筛搞),然后不断消去即可

这样就变成了nlogn的复杂度

注意这道题最好写双hash,由于pascal不能自然溢出,我卡出一个可以过的单hash……

 1 const mo=9875321;
 2       bas=37;
 3
 4 var p,v,d,h:array[0..500010] of longint;
 5     len,l,r,m,j,k,i,n,t:longint;
 6     s:ansistring;
 7
 8 function hash(x,y:longint):longint;
 9   begin
10     exit((h[x]-int64(h[y+1])*int64(d[y-x+1]) mod mo+mo) mod mo);
11   end;
12
13 begin
14   readln(n);
15   for i:=2 to n do
16   begin
17     if v[i]=0 then
18     begin
19       v[i]:=i;
20       inc(t);
21       p[t]:=i;
22     end;
23     for j:=1 to t do
24     begin
25       if i*p[j]>n then break;
26       v[i*p[j]]:=p[j];
27       if i mod p[j]=0 then break;
28     end;
29   end;
30   d[0]:=1;
31   for i:=1 to n do
32     d[i]:=d[i-1]*bas mod mo;
33   readln(s);
34   for i:=n downto 1 do
35     h[i]:=(h[i+1]*bas+ord(s[i])) mod mo;
36   readln(m);
37   for i:=1 to m do
38   begin
39     readln(l,r);
40     len:=(r-l+1);
41     k:=len;
42     while k>1 do
43     begin
44       j:=v[k];
45       while (len mod j=0) and (hash(l,r-len div j)=hash(l+len div j,r)) do len:=len div j;
46       while k mod j=0 do k:=k div j;
47     end;
48     writeln(len);
49   end;
50 end.

时间: 2024-10-25 10:44:12

bzoj2795的相关文章

【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),表示询

【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)$线筛

【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

[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个小

bzoj-2795 A Horrible Poem

题意: 给出一个长度为N的字符串,有Q次询问: 每次询问给出一个区间,求区间最短循环节长度: N<=500000,Q<=2000000: 题解: 这题数据范围简直丧病= =渣电脑3s真的能跑出来吗... 不过这题在BZ上是可做的,50s我的程序10s出解了: 首先这问题画一画发现它绝对不是什么数据结构能维护的,因为这东西毫无可并性: 硬说的话多个相同的的连在一起的循环节可以合并变长,然并卵: 所以如果考虑暴力一些呢? 发现循环节长度一定是区间长度n的约数,可以枚举n的约数: 验证利用RKhas