码迷,mamicode.com
首页 > 其他好文 > 详细

hdu 5726 GCD 倍增+ 二分

时间:2016-07-20 21:02:09      阅读:171      评论:0      收藏:0      [点我收藏+]

标签:

题目链接

 

给n个数, 定义一个运算f[l,r] = gcd(al, al+1,....ar)。 然后给你m个询问, 每次询问给出l, r。 求出f[l, r]的值以及有多少对l‘, r‘ 使得f[l, r] = f[l‘, r‘]。

 

第一个很简单, 用倍增的思想就可以了。 

然后是第二个, 我们枚举每一个左端点i, 显然f[i, j]是只降不增的。 那么我们可以二分找到所有使得f[i, j]下降的值j。 因为gcd每次至少变为原来的二分之一, 而ai最大为1e9. 所以最多只有log2(1e9)个这样的点。 我们都找出来然后放到map里就可以了。 具体看代码

#include <bits/stdc++.h>

using namespace std;
#define ll long longint n;
const int maxn = 1e5+5;
int a[maxn], f[maxn][20], mm[maxn];
map <int, ll> mp;
int gcd(int a, int b)
{
    return b?gcd(b, a%b):a;
}
void initrmq()
{
    mm[0] = -1;
    for(int i = 1; i <= n; i++) {
        mm[i] = ((i&(i-1))==0)?mm[i-1]+1:mm[i-1];
    }
    for(int j = 1; j < 17; j++) {
        for(int i = 1; i + (1<<j)-1 <= n; i++) {
            f[i][j] = gcd(f[i][j-1], f[i+(1<<(j-1))][j-1]);
        }
    }
}
int query(int l, int r)
{
    int k = mm[r-l+1];
    return gcd(f[l][k], f[r-(1<<k)+1][k]);
}
void pre()
{
    for(int i = 1; i <= n; i++) {
        int g = f[i][0];
        int L = i, tmp;
        while(L <= n) {
            int l = L, r = n;
            while(l <= r) {
                int mid = l+r>>1;
                if(query(i, mid) == g) {
                    tmp = mid;
                    l = mid+1;
                } else {
                    r = mid-1;
                }
            }
            mp[g] += (tmp-L+1);
            L = tmp+1;
            g = gcd(g, f[L][0]);
        }
    }
}
int main()
{
    int t, m, l, r;
    cin>>t;
    for(int casee = 1; casee <= t; casee++) {
        cin>>n;
        for(int i = 1; i <= n; i++) {
            scanf("%d", &a[i]);
            f[i][0] = a[i];
        }
        mp.clear();
        initrmq();
        pre();
        cin>>m;
        printf("Case #%d:\n", casee);
        for(int i = 0; i < m; i++) {
            scanf("%d%d", &l, &r);
            int ans = query(l, r);
            printf("%d %lld\n", ans, mp[ans]);
        }
    }
}

 

hdu 5726 GCD 倍增+ 二分

标签:

原文地址:http://www.cnblogs.com/yohaha/p/5689514.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!