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 }
  • 相关阅读:
    java模式及其应用场景
    redis配置密码 redis常用命令
    Redis可视化工具Redis Desktop Manager使用
    String类和StringBuffer类的区别
    centos下搭建redis集群
    eclipse maven项目中使用tomcat插件部署项目
    什么是反向代理,如何区别反向与正向代理
    数据库连接池的原理
    归并排序
    asio-kcp源码分析
  • 原文地址:https://www.cnblogs.com/kirai/p/5978827.html
Copyright © 2011-2022 走看看