BZOJ2795:[Poi2012]A Horrible Poem 暴力+hash(&&BZOJ2890)
Jan 23, 2015 04:22:48 PM
思路:
一开始的暴力非常容易:对于每一组询问直接暴力枚举答案即可.易知答案仅可能是字串长度的约数,再利用hash\(O(1)\)判断.因此单组询问的复杂度\(O(\sqrt{n})\).这种方法比较卡常数.
其实,存在一种更加科学的方法.
我们将长度分解质因数,考虑每个质因子的幂次.这样即可在\(O(logn)\)的时间内出解.十分科学.
#include<cstdio>
#include<cstring>
#include<cctype>
#include<iostream>
#include<algorithm>
using namespace std;
#define INF 0x3f3f3f3f
namespace Fio{
inline int getc(){
static const int L=1<<15;static char buf[L],*S=buf,*T=buf;
if(S==T){T=(S=buf)+fread(buf,1,L,stdin);if(S==T)return EOF;}
return*S++;
}
template<typename T>inline void Get(T&x){
int c;while(!isdigit(c=getc()));x=c-'0';while(isdigit(c=getc()))x=(x<<1)+(x<<3)+c-'0';
}
char buf[20000000],*o=buf;
template<typename T>inline void Print(T x){
static int stk[100];
if(x<0)x=-x,*o++='-';
if(!x)*o++=48;else{int top=0;for(;x;x/=10)stk[++top]=x%10;for(int i=top;i;--i)*o++=48+stk[i];}
*o++='\n';
}
inline void Final(){fwrite(buf,1,o-buf,stdout);}
}
#define N 500010
typedef long long LL;
static const int seed=131;
static const int mod=(1e9)+9;
int n,f[N],mi[N];char s[N];
inline int get(int l,int r){
return (f[l]-(LL)f[r+1]*mi[r-l+1]%mod+mod)%mod;
}
inline bool same(int l1,int r1,int l2,int r2){
return get(l1,r1)==get(l2,r2);
}
int p[N],minp[N],cnt;bool np[N];
inline void pre(int n){
register int i,j;
for(i=2;i<=n;++i){
if(!np[i])p[++cnt]=minp[i]=i;
for(j=1;j<=cnt&&p[j]*i<=n;++j){
np[i*p[j]]=1,minp[i*p[j]]=min(minp[i],p[j]);
if(i%p[j]==0)break;
}
}
}
inline int Solve(int l,int r){
int len=r-l+1;if(len==1)return 1;
int tmp=len,res=len;
while(tmp!=1){
int nowp=minp[tmp],ans=1,calclen=len,t=1;
while(1){
if(calclen==len||same(l,l+(len-calclen)-1,r-(len-calclen)+1,r))ans=max(ans,t);
if(calclen%nowp!=0)break;
t*=nowp,calclen/=nowp;
}
for(res/=ans;tmp%nowp==0;tmp/=nowp);
}
return res;
}
int main(){
using namespace Fio;
scanf("%d",&n);scanf("%s",s+1);
register int i;
for(i=n;i>=1;--i)f[i]=((LL)seed*f[i+1]+s[i]-'a')%mod;
for(mi[0]=1,i=1;i<=n;++i)mi[i]=(LL)mi[i-1]*seed%mod;
pre(n);
int m;Get(m);int l,r;
while(m--){
Get(l),Get(r);
Print(Solve(l,r));
}
Final();
return 0;
}