Time Limit: 7000/3500 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 2229 Accepted Submission(s): 252
Problem Description
The shorter, the simpler. With this problem, you should be convinced of this truth.
You are given an array A of N postive integers, and M queries in the form (l,r). A function F(l,r) (1≤l≤r≤N) is defined as:
F(l,r)={AlF(l,r−1) modArl=r;l<r.
You job is to calculate F(l,r), for each query (l,r).
You are given an array A of N postive integers, and M queries in the form (l,r). A function F(l,r) (1≤l≤r≤N) is defined as:
F(l,r)={AlF(l,r−1) modArl=r;l<r.
You job is to calculate F(l,r), for each query (l,r).
Input
There are multiple test cases.
The first line of input contains a integer T, indicating number of test cases, and T test cases follow.
For each test case, the first line contains an integer N(1≤N≤100000).
The second line contains N space-separated positive integers: A1,…,AN (0≤Ai≤109).
The third line contains an integer M denoting the number of queries.
The following M lines each contain two integers l,r (1≤l≤r≤N), representing a query.
The first line of input contains a integer T, indicating number of test cases, and T test cases follow.
For each test case, the first line contains an integer N(1≤N≤100000).
The second line contains N space-separated positive integers: A1,…,AN (0≤Ai≤109).
The third line contains an integer M denoting the number of queries.
The following M lines each contain two integers l,r (1≤l≤r≤N), representing a query.
Output
For each query(l,r), output F(l,r) on one line.
Sample Input
1
3
2 3 3
1
1 3
Sample Output
2
题意:给你一个n个数的序列,以及m个查询,每次查询一个区间[l,r],求a[l]%a[l+1]%a[l+2]...%a[r]
思路:易知,比当前大的数取模没意义,实际取模的次数是log次(取模至少会减少一半),那么问题就转化为如何在所查询的区间跳着来取模,每次只对比当前小的数取模
iky:::设ans为当前的值,上一次取模的位置为p,那么我们只需要在p的右边找到一个数比ans小的第一个数,ans对那么数取模,p跳到那么位置即可。最多跳log次,每次二分一个log,复杂度就是nloglog
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <cstdio> #include <cstring> #include <iostream> #include <cmath> #include <queue> #include <algorithm> #include <stack> #include <queue> #include <map> #include <set> #include <vector> #include <cstdlib> using namespace std; typedef long long ll; const int N = 2e5 + 100; int n, m; int a[N], mm[N], mi[N][25]; void initRMQ(int n, int b[]) { mm[0] = -1; for(int i = 1; i <= n; ++i) { mm[i] = ((i & (i - 1)) == 0) ? mm[i - 1] + 1 : mm[i - 1]; mi[i][0] = b[i]; } for(int j = 1; j <= mm[n]; ++j) for(int i = 1; i + (1 << j) - 1 <= n; ++i) mi[i][j] = min(mi[i][j - 1], mi[i + (1 << (j-1))][j - 1]); } int rmq(int x, int y) { if(x > y) return 0x3f3f3f3f; int k = mm[y - x + 1]; return min(mi[x][k], mi[y - (1 << k) + 1][k]); } int calc(int l, int r) { int p = l, ans = a[l]; while(p < r) { int L = 1, R = r - p + 1, tmp = R; while(L < R) { int M = (L + R) >> 1; if(rmq(p + 1, p + M) <= ans) R = M; else L = M + 1; } if(L == tmp) return ans%a[r]; p = p + L; //cout << p << endl; ans %= a[p]; } return ans%a[r]; } void solve() { scanf("%d", &n); for(int i = 1; i <= n; ++i) scanf("%d", &a[i]); int l, r; initRMQ(n, a); scanf("%d", &m); for(int i = 1; i <= m; ++i) { scanf("%d%d", &l, &r); if(l == r) printf("%d ", a[l]); else printf("%d ", calc(l, r)); } } int main() { #ifdef LOCAL freopen("in", "r", stdin); #endif int cas; while(~scanf("%d", &cas)) { while(cas --) { solve(); } } return 0; }