循环节的经典性质
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