给你一个n,n个数
m个询问,每次询问你 l,r,, a[l] % a[l+1] % a[l+2] %……a[r] 结果是多少
题解;
每次有效的取模会使结果减半,因此只有log次有效取模,每次往右找一个不大于结果的最靠左的数,ST表+二分
一个数最多只能取 logn 次模
如果 x>y,那么 x mod y<=x/2
如果y <= x/2,那么 x mod y < y <= x/2
否则y > x/2,那么 x mod y = x-y < x /2
所以就很简单了= = 还有就是一些小操作要注意
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5+100;
int a[N];
int mn[N][20];
int n;
void ST()
{
for(int i=1;i<=n;i++)
mn[i][0]=a[i];
for(int j=1;(1<<j)<=n;j++)
{
for(int i=1;i+(1<<j)-1<=n;i++)
{
mn[i][j]=min(mn[i][j-1],mn[i+(1<<(j-1))][j-1]);
}
}
}
int rmq(int i,int j)
{
int k=0;
while(1<<(k+1)<=(j-i+1)) k++;
return min(mn[i][k],mn[j-(1<<k)+1][k]);
}
int bin(int l,int r,int res)
{
int s=r+1;
while(l<=r)
{
int md=(l+r)>>1;
if(rmq(l,md)<=res) r=md-1,s=md;
else l=md+1;
}
return s;
}
int main()
{
int t;
while(scanf("%d",&t)!=EOF)
{
while(t--)
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
ST();
int m;
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
int f=0;
int ll,rr;
scanf("%d%d",&ll,&rr);
int res=a[ll];
int L=ll+1,R=rr;
while(L<=R&&res)
{
L=bin(L,R,res);
if(L<=R)
{
res%=a[L],L++;
}
}
printf("%d\n",res );
}
}
}
}