题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5726
给你n个数,q个询问,每个询问问你有多少对l r的gcd(a[l] , ... , a[r]) 等于的gcd(a[l'] ,..., a[r'])。
先用RMQ预处理gcd,dp[i][j] 表示从i开始2^j个数的gcd。
然后用map存取某个gcd所对应的l r的数量。
我们可以在询问前进行预处理,先枚举i,以i为左端点的gcd(a[i],..., a[r])的种类数不会超过log2(n),gcd呈单调不增性。(因为gcd值每次变化,至少除以2)
所以所有的gcd的种类个数最多就nlog2(n)。
明白之后,我们可以枚举i为左端点固定,然后二分一下右端点,计算每种gcd的数量。
大概理解之后就可以敲了,然后就是细节问题。
1 #include <algorithm> 2 #include <iostream> 3 #include <cstdlib> 4 #include <cstring> 5 #include <string> 6 #include <cstdio> 7 #include <vector> 8 #include <ctime> 9 #include <cmath> 10 #include <queue> 11 #include <set> 12 #include <map> 13 using namespace std; 14 #define Fill(x, y) memset((x), (y), sizeof(x)) 15 #define Rep(i, x, y) for(int i = x; i <= y; ++i) 16 #define Dow(i, x, y) for(int i = x; i >= y; --i) 17 typedef long long LL; 18 typedef pair <int, int> P; 19 typedef pair <LL, LL> PLL; 20 const LL mod = 1e9 + 7; 21 const LL inf = 1e18; 22 const int N = 1e5 + 10; 23 int GCD(int a, int b) { 24 return b ? GCD(b, a % b) : a; 25 } 26 27 int dp[N][20]; 28 map <int , LL> mp; 29 30 void ST(int n) { 31 for(int k = 1 ; k < 19 ; ++k) { 32 for(int i = 1 ; i + (1 << k) - 1 <= n ; ++i) { 33 dp[i][k] = GCD(dp[i][k - 1] , dp[i + (1 << (k - 1))][k - 1]); 34 } 35 } 36 } 37 38 int rmq(int l , int r) { 39 int k = log2(r - l + 1); 40 return GCD(dp[l][k] , dp[r - (1 << k) + 1][k]); 41 } 42 43 int main() 44 { 45 int t , n , q , u , v; 46 scanf("%d" , &t); 47 for(int ca = 1 ; ca <= t ; ++ca) { 48 scanf("%d" , &n); 49 for(int i = 1 ; i <= n ; ++i) 50 scanf("%d" , &dp[i][0]); 51 ST(n); 52 mp.clear(); 53 for(int i = 1 ; i <= n ; ++i) { 54 int l , r , temp = i , gcd = dp[i][0] , s = i; 55 do { 56 l = temp , r = n; 57 s = l , gcd = rmq(i , s); 58 while(l <= r) { 59 int mid = (l + r) / 2; 60 temp = mid; 61 if(rmq(i , mid) < gcd) { 62 r = mid - 1; 63 temp = mid - 1; 64 } 65 else { 66 l = mid + 1; 67 } 68 } 69 mp[gcd] += (LL)(temp - s + 1); 70 temp++; 71 }while(temp <= n); 72 } 73 printf("Case #%d: " , ca); 74 scanf("%d" , &q); 75 while(q--) { 76 scanf("%d %d" , &u , &v); 77 int gcd = rmq(u , v); 78 printf("%d %lld " , gcd , mp[gcd]); 79 } 80 } 81 return 0; 82 }