zoukankan      html  css  js  c++  java
  • HDU 5726 GCD

    题意:动态查询区间的gcd,和gcd的值的个数。

    分析:gcd的查找可以线段树,val(node) = gcd(val(left),val(val)),我是用ST表搞的。

    然后查询这个值的区间有多少个。

    简单说就是,这个gcd 不会很多,可以分区间hash好。

    二分写的很糟。

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int maxn = 100000+5;
    
    int n;
    int a[maxn];
    int d[maxn][20];
    
    int gcd(int a,int b)
    {
        return b==0 ? a : gcd(b,a%b);
    }
    
    void init(int* a)
    {
        for(int i=0; i<n; i++)
            d[i][0] = a[i];
        for(int j=1; (1<<j)<=n; j++)
            for(int i=0; i+(1<<j)-1<n; i++)
                d[i][j] = gcd(d[i][j-1],d[i+(1<<(j-1))][j-1]);
    }
    
    int sol(int L,int R)
    {
        int k = 0;
        while(1<<(k+1)<=R-L+1) k++;
        return gcd(d[L][k],d[R-(1<<k)+1][k]);
    }
    
    int main()
    {
        //freopen("in.txt","r",stdin);
        int t;
        scanf("%d",&t);
        int kase = 1;
        while(t--)
        {
            scanf("%d",&n);
            for(int i=0; i<n; i++)
                scanf("%d",&a[i]);
    
            init(a);
    
            map<int,long long> rec;
            for(int i=0; i<n; i++)
            {
                int g = d[i][0],L=i;
    
                while(L<n)
                {
                    int l = L;
                    int r = n;
                    g = sol(i,L);
                    while(l<r)
                    {
                        if(r-l==1) {
                            if(sol(i,r)==g&&r!=n) {
                                l = r;
                                break;
                            }
                            else break;
                        }
                        int mid = l+(r-l)/2;
    
                        int tmp = sol(i,mid);
    
                        if(tmp==g)
                            l = mid;
                        else r = mid-1;
                    }
                    //printf("%d %d
    ",l,l-L+1);
                    rec[g] += (l-L)+1;
                    L = l+1;
                }
            }
    
            printf("Case #%d:
    ",kase++);
    
            int q;
            scanf("%d",&q);
            while(q--)
            {
                int l,r;
                scanf("%d%d",&l,&r);
                l--;
                r--;
                int tmp = sol(l,r);
                printf("%d %I64d
    ",tmp,rec[tmp]);
    
            }
    
        }
        return 0;
    }
    View Code
  • 相关阅读:
    实验四
    实验三
    实验二
    实验一
    6
    5
    4
    3
    shiyan2
    实验1
  • 原文地址:https://www.cnblogs.com/TreeDream/p/7230771.html
Copyright © 2011-2022 走看看