循环节的经典性质

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.
View Code

 

posted on 2015-05-30 20:19  acphile  阅读(384)  评论(0编辑  收藏  举报