• HDU 5726 GCD (RMQ + 二分)


    题目链接: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 }
  • 相关阅读:
    使用postman模拟上传文件到springMVC的坑:the request was rejected because no multipart boundary was found
    win10 安装多个版本的jdk,如何切换
    String类的substring方法
    tomcat7.0配置CORS(跨域资源共享)
    win7下安装centos6.5后,开机无法进入选择双系统启动界面,只能启动centos的解决办法
    java位运算
    JDK源码--ArrayList浅析
    使用Jasperreporter生成入库出库单打印等报表操作
    centos6.5下安装zip格式的tomcat7和tomcat8,并同时运行
    Centos7配置文件共享服务器SAMBA三步曲(转)
  • 原文地址:https://www.cnblogs.com/Recoder/p/5693190.html
Copyright © 2020-2023  润新知