您的位置:首页 > 其它

【51nod 1203】【JZPLCM】【莫队算法】

2017-02-23 17:21 148 查看

题目大意

给出一列数,求一段区间的lcm。

解题思路

离线询问,对小于sqrt(n)的质因子暴力求出,rmq解决询问。这样之后就只最多剩下一个质因子,可以使用莫队用桶维护。

code

#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LF double
#define LL long long
#define Min(a,b) ((a<b)?a:b)
#define Max(a,b) ((a>b)?a:b)
#define Fo(i,j,k) for(int i=j;i<=k;i++)
#define Fd(i,j,k) for(int i=j;i>=k;i--)
using namespace std;
int const Mxn=5*1e4;
int N,Q,Size,A[Mxn+9],Ha[Mxn+9],Cnt[Mxn+9],F[Mxn+9][17],Two[17],Ans[Mxn+9],Mo=1e9+7;
struct Rec{int L,R,P;};
Rec B[Mxn+9];
bool Cmp(Rec X,Rec Y){
return ((X.L-1)/Size<(Y.L-1)/Size)||(((X.L-1)/Size==(Y.L-1)/Size)&&(X.R<Y.R));
}
int Pow(LL X,int Y){
LL Z=1;
while(Y){
if(Y&1)Z=Z*X%Mo;
X=X*X%Mo;
Y>>=1;
}
return Z;
}
int Calc(int L,int R){
int X=log(R-L+1)/log(2);
return Max(F[L][X],F[R-Two[X]+1][X]);
}
int main(){
freopen("d.in","r",stdin);
freopen("d.out","w",stdout);
scanf("%d%d",&N,&Q);int Mx=0,Mx2=log(N)/log(2),Tmp,Ok;Size=sqrt(N);
Two[0]=1;Fo(i,1,Mx2)Two[i]=Two[i-1]<<1;
Fo(i,1,N)scanf("%d",&A[i]),Mx=Max(Mx,A[i]);Mx=sqrt(Mx);
Fo(i,1,Q)scanf("%d%d",&B[i].L,&B[i].R),B[i].P=i,Ans[i]=1;
Fo(i,2,Mx){
Tmp=sqrt(i);Ok=1;
Fo(j,2,Tmp)if(i%j==0){Ok=0;break;}
if(Ok){
Fo(j,1,N){
F[j][0]=0;
while(A[j]%i==0)F[j][0]++,A[j]/=i;
}
Fo(k,1,Mx2)Fd(j,N-Two[k-1],1)F[j][k]=Max(F[j][k-1],F[j+Two[k-1]][k-1]);
Fo(j,1,Q)Ans[j]=1ll*Ans[j]*Pow(i,Calc(B[j].L,B[j].R))%Mo;
}
}
sort(B+1,B+Q+1,Cmp);
int Next;LL Now;
Fo(i,1,Q)if(((B[i].L-1)/Size!=(B[i-1].L-1)/Size)||(i==1)){
if(B[i].P==14){
int bb;
bb++;
}
Now=1;Next=(B[i].L-1)/Size*Size+Size;
Fo(j,1,Mxn)Cnt[j]=0;
Fo(j,Next+1,B[i].R){
if(!Cnt[A[j]])Now=(Now*A[j])%Mo;
Cnt[A[j]]++;
}
LL Tmp=Now;
Fo(j,B[i].L,Min(Next,B[i].R)){
if(!Cnt[A[j]])Now=(Now*A[j])%Mo;
Cnt[A[j]]++;
}
Fo(j,B[i].L,Min(Next,B[i].R))Cnt[A[j]]--;
Ans[B[i].P]=1ll*Ans[B[i].P]*Now%Mo;Now=Tmp;
}else{
if(B[i].P==14){
int bb;
bb++;
}
Fo(j,Max(Next+1,B[i-1].R+1),B[i].R){
if(!Cnt[A[j]])Now=(Now*A[j])%Mo;
Cnt[A[j]]++;
}
LL Tmp=Now;
Fo(j,B[i].L,Min(Next,B[i].R)){
if(!Cnt[A[j]])Now=(Now*A[j])%Mo;
Cnt[A[j]]++;
}
Fo(j,B[i].L,Min(Next,B[i].R))Cnt[A[j]]--;
Ans[B[i].P]=1ll*Ans[B[i].P]*Now%Mo;Now=Tmp;
}
Fo(i,1,Q)printf("%d\n",Ans[i]);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: