Live2d Test Env

HDU - 4676 :Sum Of Gcd (莫队&区间gcd公式)

 

Given you a sequence of number a 1, a 2, ..., a n, which is a permutation of 1...n.
You need to answer some queries, each with the following format:
Give you two numbers L, R, you should calculate sum of gcd(a[i], a[j]) for every L <= i < j <= R.

InputFirst line contains a number T(T <= 10),denote the number of test cases.
Then follow T test cases.
For each test cases,the first line contains a number n(1<=n<= 20000).
The second line contains n number a 1,a 2,...,a n.
The third line contains a number Q(1<=Q<=20000) denoting the number of queries.
Then Q lines follows,each lines contains two integer L,R(1<=L<=R<=n),denote a query.OutputFor each case, first you should print "Case #x:", where x indicates the case number between 1 and T.
Then for each query print the answer in one line.Sample Input

1
5
3 2 5 4 1
3
1 5
2 4
3 3

Sample Output

Case #1:
11
4
0

题意:给定N个数,已经Q次询问,每次询问这个区间的两两GCD之和。

思路:之前做过一个类似的题,问区间两两有多少对互质,维护每个数的因子个数,即把下面的公式换成莫比乌斯系数瞎搞即可。

51nod1439:https://www.cnblogs.com/hua-dong/p/9141249.html

这里直接推。不过上次自己推的,这里我没有想出来,百度了一下。

 

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=20010;
struct in{int l,r,id;}s[maxn];
bool cmp(in w,in v){
    if(w.l/100==v.l/100) return w.r<v.r;
    return w.l/100<v.l/100;
}
int a[maxn],ans[maxn],vis[maxn],phi[maxn];
int num[maxn],p[maxn],cnt,res;
vector<int>G[maxn];
void solve()
{
    phi[1]=1;
    for(int i=2;i<maxn;i++){
        if(!vis[i]) p[++cnt]=i,phi[i]=i-1;
        for(int j=1;j<=cnt&&i*p[j]<maxn;j++){
            phi[i*p[j]]=phi[i]*phi[p[j]]; vis[i*p[j]]=1;
            if(i%p[j]==0){phi[i*p[j]]=phi[i]*p[j]; break;}
        }
    }
    for(int i=1;i<maxn;i++){
        for(int j=i;j<maxn;j+=i) G[j].push_back(i);
    }
}
void add(int x)
{
    for(int i=0;i<G[x].size();i++){
        res+=phi[G[x][i]]*num[G[x][i]];
    }
    for(int i=0;i<G[x].size();i++) num[G[x][i]]++;
}
void del(int x)
{
    for(int i=0;i<G[x].size();i++) num[G[x][i]]--;
    for(int i=0;i<G[x].size();i++){
        res-=phi[G[x][i]]*num[G[x][i]];
    }
}
int main()
{
    solve();
    int T,N,Q,L,R,C=0;
    scanf("%d",&T);
    while(T--){
        scanf("%d",&N);
        rep(i,1,N) scanf("%d",&a[i]);
        scanf("%d",&Q);
        rep(i,1,Q) scanf("%d%d",&s[i].l,&s[i].r),s[i].id=i;
        sort(s+1,s+Q+1,cmp);
        L=0; R=0; res=0; memset(num,0,sizeof(num));
        rep(i,1,Q){
            while(L<s[i].l) del(a[L++]);
            while(R>s[i].r) del(a[R--]);
            while(L>s[i].l) add(a[--L]);
            while(R<s[i].r) add(a[++R]);
            ans[s[i].id]=res;
        }
        printf("Case #%d:\n",++C);
        rep(i,1,Q) printf("%d\n",ans[i]);
    }
    return 0;
}

 

posted @ 2018-11-05 15:35  nimphy  阅读(314)  评论(0编辑  收藏  举报