hdu 5381 莫队...


The sum of gcd

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 854    Accepted Submission(s): 363


Problem Description
You have an array  A,the length of  A is  n
Let  f(l,r)=ri=lrj=igcd(ai,ai+1....aj)
 

Input
There are multiple test cases. The first line of input contains an integer T, indicating the number of test cases. For each test case:
First line has one integers  n
Second line has  n integers  Ai
Third line has one integers  Q,the number of questions
Next there are Q lines,each line has two integers  l, r
1T3
1n,Q104
1ai109
1l<rn
 

Output
For each question,you need to print  f(l,r)
 

Sample Input
 
   
2 5 1 2 3 4 5 3 1 3 2 3 1 4 4 4 2 6 9 3 1 3 2 4 2 3
 

Sample Output
 
   
9 6 16 18 23 10


最难的不是莫队。。 而是。。 处理转移关系。。 神题

rmq可以用来预处理gcd也是第一次知道。。 

利用gcd特殊性质优化

#include  
using namespace std;
#define fi first
#define se second
const int maxn = 10010;
typedef pair pii;
typedef long long ll;
int gcd[maxn][20], mm[maxn];
int n,q,a[maxn], unit;
vector lef[maxn], rig[maxn];
ll ans[maxn];
struct node{
    int l, r, id;
    bool operator<(const node & b) const{
        if( l/unit == b.l/unit) return r < b.r;
        return l/unit < b.l/unit;
    }
}Query[maxn];
void init(){
    mm[0] = -1;
    for(int i=1; i<=n; i++){
        mm[i] = (i&(i-1)) == 0?mm[i-1]+1:mm[i-1];
        gcd[i][0] = a[i];
    }
    for(int j=1; j<=mm[n]; j++)
        for(int i=1; i+(1<>1;
                if(query(mid, i) == g) R = mid-1, ans = mid;
                else L = mid + 1;
            }
            lef[i].push_back(make_pair(g, ans));
            if(ans == 1) break;
            R = ans - 1; L = 1; g = query(R, i);
        }
    }
    for(int i=1; i<=n; i++){
        int L = i, R = n, g = a[i], mid;
        while(true){
            while(L <= R){
                mid = (L+R+1)>>1;
                if(query(i, mid) == g) L = mid+1, ans = mid;
                else R = mid-1;
            }
            rig[i].push_back(make_pair(g, ans));
            if(ans == n) break;
            L = ans + 1, R = n, g = query(i, L);
        }
    }
}
ll LEFT(int x, int L){
    int p = x;
    ll ans = 0;
    int size = lef[x].size();
    for(int i=0; i R) break;
    }
    return ans;
}
void work(){
    int L = 1;
    int R = 0;
    sort(Query+1, Query+q+1);
    ll cnt = 0;
    for(int i=1; i<=q; i++){
        while(RQuery[i].r)
            cnt -= LEFT(R--, L);
        while(LQuery[i].l)
            cnt += RIGHT(--L, R);
        ans[Query[i].id] = cnt;
    }
}
int main(){
    int T;
    cin>>T;
    while(T--){
        cin>>n;
        unit = sqrt(n);
        for(int i=1; i<=n; i++)
            scanf("%d", a+i);
        init();
        go();
        scanf("%d", &q);
        for(int i=1; i<=q; i++){
            scanf("%d %d", &Query[i].l, &Query[i].r);
            Query[i].id = i;
        }
        work();
        for(int i=1; i<=q; i++)
            printf("%I64d\n", ans[i]);
    }
    return 0;
}


你可能感兴趣的:(多校联合训练,hdu题解)