zoukankan      html  css  js  c++  java
  • GCD(st表+二分)

    GCD

    Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
    Total Submission(s): 3432    Accepted Submission(s): 1227


    Problem Description

    Give you a sequence of N(N100,000) integers : a1,...,an(0<ai1000,000,000). There are Q(Q100,000) queries. For each query l,r you have to calculate gcd(al,,al+1,...,ar) and count the number of pairs(l,r)(1l<rN)such that gcd(al,al+1,...,ar) equal gcd(al,al+1,...,ar).
     

    Input

    The first line of input contains a number T, which stands for the number of test cases you need to solve.

    The first line of each case contains a number N, denoting the number of integers.

    The second line contains N integers, a1,...,an(0<ai1000,000,000).

    The third line contains a number Q, denoting the number of queries.

    For the next Q lines, i-th line contains two number , stand for the li,ri, stand for the i-th queries.
     

    Output

    For each case, you need to output “Case #:t” at the beginning.(with quotes, t means the number of the test case, begin from 1).

    For each query, you need to output the two numbers in a line. The first number stands for gcd(al,al+1,...,ar) and the second number stands for the number of pairs(l,r) such that gcd(al,al+1,...,ar) equal gcd(al,al+1,...,ar).
     

    Sample Input

    1
    5
    1 2 4 6 7
    4
    1 5
    2 4
    3 4
    4 4

    Sample Output

    Case #1:
    1 8
    2 4
    2 4
    6 1
     
     
    题意:第一行T代表测试组数,第二行一个整数 N 代表长为 N 的序列,再一行是一个整数 Q ,代表有 Q 次询问,
    然后 Q 行,每行两个整数 l,r 输出区间[l,r]的gcd 和有多少个区间 gcd 等于 gcd[l,r]
     
    题解:想了很久,没想到好办法,后来发现RMQ这种问题,线段树还是不行的,如果离线的话,st表查询时间复杂度比线段树更小,为O(1)
    st算法是用来求解给定区间RMQ的最值
    学了st表后,查询有多少区间gcd==gcd[l,r]还是不知道怎么搞,题解是,用二分离线预处理...
     1 #include<iostream>
     2 #include<cstdlib>
     3 #include<cstring>
     4 #include<cstdio>
     5 #include<map>
     6 using namespace std;
     7 
     8 #define LL long long
     9 #define MAXN 100005
    10 
    11 int n;
    12 int num[MAXN];
    13 int mn[MAXN];
    14 int dp[MAXN][20];
    15 map<int,LL> res;
    16 
    17 int gcd(int a,int b)
    18 {   return b==0?a:gcd(b,a%b);}
    19 
    20 void Init()
    21 {
    22     mn[0]=-1;
    23     for (int i=1;i<=n;i++)
    24     {
    25         mn[i]=((i&(i-1))==0)?mn[i-1]+1:mn[i-1];
    26         dp[i][0]=num[i];
    27     }
    28     for (int j=1;j<=mn[n];j++)
    29         for (int i=1;i+(1<<j)-1<=n;i++)
    30         {
    31             dp[i][j]=gcd(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
    32         }
    33 }
    34 
    35 int st_calc(int l,int r)
    36 {
    37     int k = mn[r-l+1];
    38     return gcd(dp[l][k],dp[r-(1<<k)+1][k]);
    39 }
    40 
    41 void erfen()
    42 {
    43     res.clear();
    44     for (int i=1;i<=n;i++)  //以i为左起点的区间的所有公约数
    45     {
    46         int cur = i , gc = num[i];  //用二分求出
    47         while (cur <= n)
    48         {
    49             int l=cur,r=n;
    50             while(l<r)
    51             {
    52                 int mid = (l+r+1)>>1;
    53                 if (st_calc(i,mid)==gc) l=mid;
    54                 else r = mid -1;
    55             }
    56             if (res.count(gc)) res[gc]+=l-cur+1;
    57             else res[gc]=l-cur+1;
    58             cur = l + 1;
    59             if (cur<=n)
    60                 gc = gcd(gc,num[cur]);
    61         }
    62     }
    63 }
    64 
    65 int main()
    66 {
    67     int t;
    68     int cas=0;
    69     scanf("%d",&t);
    70     while (t--)
    71     {
    72         scanf("%d",&n);
    73         for (int i=1;i<=n;i++)
    74             scanf("%d",&num[i]);
    75         Init();
    76 
    77         erfen();
    78 
    79         int q;
    80         scanf("%d",&q);
    81         printf("Case #%d:
    ",++cas);
    82         while (q--)
    83         {
    84             int x,y;
    85             scanf("%d%d",&x,&y);
    86             int kk = st_calc(x,y);
    87             printf("%d %lld
    ",kk,res[kk]);
    88         }
    89     }
    90     return 0;
    91 }
    View Code
     
     
  • 相关阅读:
    [Python] from scipy import sparse 报 DLL load failed:找不到指定模块错误
    LPC43xx系列使用IAP的注意事项
    SecureCRT中设置 为回车换行,和 的行为一致
    GSM07.10协议中串口复用的注意事项
    Lua在单片机中的移植
    ALINX公众号
    黑金博客搬家了
    2014年黑金FPGA原创教程规划发布
    【黑金原创教程】【FPGA那些事儿-驱动篇I 】连载导读
    【黑金原创教程】【FPGA那些事儿-驱动篇I 】【实验一】流水灯模块
  • 原文地址:https://www.cnblogs.com/haoabcd2010/p/6670939.html
Copyright © 2011-2022 走看看