zoukankan      html  css  js  c++  java
  • [HDOJ5726]GCD(RMQ,二分)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5726

    题意:给定数列,求区间[L,R]的GCD的值,并求出有多少个子区间满足和[L,R]的GCD相等。

    RMQ预处理所有区间的GCD,枚举所有区间的左边界i,起初固定右边界j,二分枚举右边界j的最大值,使得[i,j]区间内的GCD不变,更新对应GCD的值,大小为j-i。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 typedef long long LL;
     5 const int maxn = 100100;
     6 int n, q;
     7 LL a[maxn];
     8 LL dp[maxn][30];
     9 map<LL, LL> cnt;
    10 
    11 LL gcd(LL x, LL y) {
    12   return y == 0 ? x : gcd(y, x%y);
    13 }
    14 
    15 void st() {
    16   for(int i = 1; i <= n; i++) dp[i][0] = a[i];
    17   for(int j = 1; (1 << j) <= n; j++) {
    18      for(int i = 1; i + (1 << j) - 1 <= n; i++) {
    19         dp[i][j] = gcd(dp[i][j-1], dp[i+(1<<(j-1))][j-1]);
    20     }
    21   }
    22 }
    23 
    24 LL query(int l, int r) {
    25   int j = 0;
    26   while(1 << (j + 1) <= r - l + 1) j++;
    27   return gcd(dp[l][j], dp[r-(1<<j)+1][j]);
    28 }
    29 
    30 inline bool scan_d(LL &num) {
    31     char in;bool IsN=false;
    32     in=getchar();
    33     if(in==EOF) return false;
    34     while(in!='-'&&(in<'0'||in>'9')) in=getchar();
    35     if(in=='-'){ IsN=true;num=0;}
    36     else num=in-'0';
    37     while(in=getchar(),in>='0'&&in<='9'){
    38         num*=10,num+=in-'0';
    39     }
    40     if(IsN) num=-num;
    41     return true;
    42 }
    43 
    44 int main() {
    45   //freopen("in", "r", stdin);
    46   int T, _ = 1;
    47   scanf("%d", &T);
    48   int l, r;
    49   while(T--) {
    50     scanf("%d", &n);
    51     for(int i = 1; i <= n; i++) {
    52       scan_d(a[i]);
    53     }
    54     st(); cnt.clear();
    55     for(int i = 1; i <= n; i++) {
    56       int j = i;
    57       while(j <= n) {
    58         LL cur = query(i, j);
    59         int lo = j, hi = n;
    60         while(lo <= hi) {
    61           int mid = (lo + hi) >> 1;
    62           if(query(i, mid) >= cur) lo = mid + 1;
    63           else hi = mid - 1;
    64         }
    65         cnt[cur] += (LL)(hi - j + 1);
    66         j = hi + 1;
    67       }
    68     }
    69     printf("Case #%d:
    ", _++);
    70     scanf("%d", &q);
    71     while(q--) {
    72       scanf("%d %d", &l, &r);
    73       LL ret = query(l, r);
    74       cout << ret << " " << cnt[ret] << endl;
    75     }
    76   }
    77   return 0;
    78 }
  • 相关阅读:
    luogu_P3195 [HNOI2008]玩具装箱TOY
    CF_837D
    luogu_P3584 [POI2015]LAS
    大一下存活纪实
    Mathematical Logic for Computer Science 读书笔记
    集训补题合集
    图论笔记4 平面图与可平面图
    软件分析笔记3 DFA
    软件分析笔记2 IR
    软件分析笔记1 Intro
  • 原文地址:https://www.cnblogs.com/kirai/p/5978827.html
Copyright © 2011-2022 走看看