zoukankan      html  css  js  c++  java
  • 2016暑假多校联合---GCD

    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
    思路:我们注意观察gcd(al​​,al+1​​,...,ar​​),当l固定不动的时候,r=l...nr=l...n时,我们可以容易的发现,随着rr的増大,gcd(al​​,al+1​​,...,ar​​)是递减的,同时gcd(al​​,al+1​​,...,ar​​)最多 有log 1000,000,000个不同的值,为什么呢?因为al​​最多也就有log 1000,000,000个质因数所以我们可以在log级别的时间处理出所有的以L开头的左区间的gcd(al​​,al+1​​,...,ar​​) 那么我们就可以在n log 1000,000,000的时间内预处理出所有的gcd(al​​,al+1​​,...,ar​​)然后我们可以用一个map来记录,gcd值为key的有多少个 然后我们就可以对于每个询问只需要查询对应gcd(al​​,al+1​​,...,ar​​)为多少,然后再在map 里面查找对应答案即可.

     代码如下:

    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #include <cmath>
    #include <map>
    #include <vector>
    using namespace std;
    int a[100005];
    
    vector<pair<int,int> > v[100005];
    map<int,long long>ans;
    
    int __gcd(int x,int y)
    {
        int r=x%y;
        x=y;
        y=r;
        if(r==0) return x;
        return __gcd(x,y);
    }
    
    int main()
    {
        int T,Case=0;
        int n;
        cin>>T;
        while(T--)
        {
            ans.clear();
            cin>>n;
            for(int i=1;i<=n;i++) scanf("%d",&a[i]);
            for(int i=1;i<=n;i++)
            {
                int tot=0;
                for(int j=0;j<v[i-1].size();j++)
                {
                    int s1=v[i-1][j].first;
                    int s2=v[i-1][j].second;
                    int  r=__gcd(a[i],s1);
                    if(tot==r) continue;
                    tot=r;
                    v[i].push_back(make_pair(r,s2));
                }
                if(tot!=a[i])   v[i].push_back(make_pair(a[i],i));
                for(int j=0;j<v[i].size();j++)
                {
                    if(j+1==v[i].size())
                        ans[v[i][j].first]+=i+1-v[i][j].second;
                    else
                        ans[v[i][j].first]+=v[i][j+1].second-v[i][j].second;
                }
            }
            cout<<"Case #"<<(++Case)<<":"<<endl;
            int Q;
            cin>>Q;
            while(Q--)
            {
                int i,l,r;
                scanf("%d%d",&l,&r);
                for(i=0;i<v[r].size();i++)
                {
                    if(v[r][i].second>l) break;
                }
                printf("%d %I64d
    ",v[r][i-1].first,ans[v[r][i-1].first]);
            }
            for(int i=0;i<100005;i++)
                v[i].clear();
        }
        return 0;
    }
  • 相关阅读:
    mysql query insert中文乱码
    git rebase
    ubuntu下怎么合并windows下分割的zip包
    [Matlab]双线性变换法设计数字带阻滤波器
    [Matlab]双线性变换法设计数字带通滤波器
    [Matlab]双线性变换法设计数字高通滤波器
    [Matlab]双线性变换法设计数字低通滤波器
    [Matlab]四种IIR滤波器纹波特性对比
    [Matlab]椭圆滤波器设计:低通、高通、带通和带阻
    [Matlab]切比雪夫Ⅱ型滤波器设计:低通、高通、带通和带阻
  • 原文地址:https://www.cnblogs.com/chen9510/p/5688170.html
Copyright © 2011-2022 走看看