题目链接
题目意思:给定如下的一个一个公式,对于给定一个n个序列,m个询问,给你个l,r求出f值
f(l,r)={A[l],f[l,r−1]moda[r],l=rl<r
思路:可以发现,一个数x最多被mod logx次,因为,如果模数比x的一般小,x变成不到一半,模数比x大,x也变成一半不到。所以最多logx次。
定义个vector数组,vec[i]表示a[i]被之后哪些数mod
一开始用一个优先队列维护,每个数到当前位置被mod还剩多少。
最后对于每个询问,logx的查询就好了。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<vector>
#include<queue>
using namespace std;
#define maxn 100111
struct NODE {
int v,num;
NODE(int x,int y) {
v=x;
num=y;
}
bool operator <(const NODE &other)const
{
if(v==other.v) return num>other.num;
return v<other.v;
}
};
vector<int>vec[maxn];
int a[maxn];
int n,m;
priority_queue<NODE> gg;
int main()
{
int t;
scanf("%d",&t);
while(t--) {
scanf("%d",&n);
while(!gg.empty()) gg.pop();
for(int i=1;i<=n;i++) vec[i].clear();
for(int i=1;i<=n;i++) {
scanf("%d",&a[i]);
while(!gg.empty()&&gg.top().v>=a[i]) {
NODE tt=gg.top();
gg.pop();
vec[tt.num].push_back(i);
gg.push(NODE(tt.v%a[i],tt.num));
}
gg.push(NODE(a[i],i));
}
scanf("%d",&m);
int l,r;
while(m--) {
scanf("%d%d",&l,&r);
int ans=a[l];
for(int i=0;i<vec[l].size();i++) {
int tt=vec[l][i];
if(tt>r) break;
ans%=a[tt];
}
printf("%d\n",ans);
}
}
return 0;
}