1. 程式人生 > >【bzoj2795】【Poi2012】A Horrible Poem

【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)$線篩最大/最小質因子,$O(logn)$分解;
    •  1 #include<bits/stdc++.h>
       2 #define rg register
       3 #define il inline 
       4 #define ull unsigned long long
       5 #define base 1234567891
       6 using namespace std;
       7 const int N=500010;
       8 int vis[N],pr[N],pt,v[N],n,m,len;
       9 ull pw[N],h[N];
      10 char gc(){
      11
      static char*p1,*p2,s[1000000]; 12 if(p1==p2)p2=(p1=s)+fread(s,1,1000000,stdin); 13 return(p1==p2)?EOF:*p1++; 14 } 15 int rd(){ 16 int x=0;char c=gc(); 17 while(c<'0'||c>'9')c=gc(); 18 while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+c-'0',c=gc(); 19 return x;
      20 } 21 void pre(){ 22 for(rg int i=2;i<=n;i++){ 23 if(!vis[i])pr[++pt]=i,v[i]=i; 24 for(rg int j=1,t;j<=pt&&pr[j]*i<=n;j++){ 25 vis[t=i*pr[j]]=1; 26 v[t]=pr[j]; 27 if(i%pr[j]==0)break; 28 } 29 } 30 } 31 ull cal(int i,int j){return h[i+j-1] - h[i-1]*pw[j];} 32 int main(){ 33 #ifndef ONLINE_JUDGE 34 freopen("bzoj2795.in","r",stdin); 35 freopen("bzoj2795.out","w",stdout); 36 #endif 37 n=rd(); pre(); 38 char ch=gc();while(!isalpha(ch))ch=gc(); 39 for(rg int i=pw[0]=1;i<=n;i++,ch=gc()){ 40 h[i]=h[i-1]*base+ch; 41 pw[i]=pw[i-1]*base; 42 } 43 m=rd(); 44 for(rg int i=1,l,r;i<=m;i++){ 45 l=rd(); r=rd(); 46 int ans=r-l+1,now=ans,t; 47 while(now>1){ 48 t=ans/v[now]; 49 if(cal(l,ans-t)==cal(l+t,ans-t))ans/=v[now]; 50 now/=v[now]; 51 } 52 printf("%d\n",ans); 53 } 54 return 0; 55 }
      bzoj2795