【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

       

 

posted @ 2019-01-08 21:29  大米饼  阅读(255)  评论(0编辑  收藏  举报