zoukankan      html  css  js  c++  java
  • HDU 5726 GCD(RMQ+二分)

    http://acm.split.hdu.edu.cn/showproblem.php?pid=5726

    题意:
    给出一串数字,现在有多次询问,每次询问输出(l,r)范围内所有数的gcd值,并且输出有多少数量区间的gcd值等于该gcd值。

    思路:

    第一问的话可以用线段树或RMQ来解决,RMQ的话简单点。

    有意思的是第二问,假设我们现在固定左端点,那么往右端扩大区间时,gcd单调不增,并且每次至少减少一倍,所以我们可以二分枚举。

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<cstdio>
     5 #include<vector>
     6 #include<stack>
     7 #include<queue>
     8 #include<cmath>
     9 #include<map>
    10 #include<set>
    11 using namespace std;
    12 typedef long long ll;
    13 typedef pair<int,int> pll;
    14 const int INF = 0x3f3f3f3f;
    15 const int maxn = 1e5 + 5;
    16 
    17 int n;
    18 int a[maxn];
    19 int d[maxn][50];
    20 
    21 map<int,ll> ans;
    22 
    23 int gcd(int a, int b)
    24 {
    25     return b==0?a:(gcd(b,a%b));
    26 }
    27 
    28 void init()
    29 {
    30     for(int i=0;i<n;i++)  d[i][0]=a[i];
    31     for(int j=1;(1<<j)<=n;j++)
    32         for(int i=0;i+(1<<j)-1<n;i++)
    33             d[i][j]=gcd(d[i][j-1],d[i+(1<<(j-1))][j-1]);
    34 }
    35 
    36 int query(int L, int R)
    37 {
    38     int k = 0;
    39     while((1<<(k+1)) <= R-L+1)  k++;
    40     return gcd(d[L][k],d[R-(1<<k)+1][k]);
    41 }
    42 
    43 int main()
    44 {
    45     //freopen("in.txt","r",stdin);
    46     int T;
    47     int kase = 0;
    48     scanf("%d",&T);
    49     while(T--)
    50     {
    51         printf("Case #%d:
    ",++kase);
    52         scanf("%d",&n);
    53         for(int i=0;i<n;i++)  scanf("%d",&a[i]);
    54         ans.clear();
    55         init();
    56         for(int i=0;i<n;i++)
    57         {
    58             int j=i, g=a[i];
    59             while(j<n)
    60             {
    61                 int l=j,r=n-1;
    62                 while(l<r)
    63                 {
    64                     int mid=(l+r)>>1;
    65                     if(query(l,r)==g)  l=mid+1;
    66                     else r=mid-1;
    67                 }
    68                 ans[g]+=l-j+1;
    69                 j=l+1;
    70                 g=gcd(g,a[j]);
    71             }
    72 
    73         }
    74         int q; scanf("%d",&q);
    75         while(q--)
    76         {
    77             int l,r;
    78             scanf("%d",&l);scanf("%d",&r);
    79             int g=query(l-1,r-1);
    80             printf("%d %lld
    ",g,ans[g]);
    81         }
    82     }
    83     return 0;
    84 }
  • 相关阅读:
    常见寻找OEP脱壳的方法
    Windows内核原理系列01
    HDU 1025 Constructing Roads In JGShining's Kingdom
    HDU 1024 Max Sum Plus Plus
    HDU 1003 Max Sum
    HDU 1019 Least Common Multiple
    HDU 1018 Big Number
    HDU 1014 Uniform Generator
    HDU 1012 u Calculate e
    HDU 1005 Number Sequence
  • 原文地址:https://www.cnblogs.com/zyb993963526/p/7653027.html
Copyright © 2011-2022 走看看