Sum Of Gcd HDU

来源:互联网 发布:java字符串转数组对象 编辑:程序博客网 时间:2024/05/17 01:31

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.
Input
First 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.
Output
For 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
把自己蠢哭了,智障去每次去dfs一个数的因子,直接预处理存起来不就好了嘛,预处理第一个询问居然直接去暴力,对自己无语啊。。。
优化版:

#include<cstdio>#include<iostream>#include<algorithm>#include<cstring>#include<cmath>#include<bitset>#include<vector>#define N 20500#define INF 10000000000#define mod 1000000007using namespace std;typedef long long  ll;vector<int> factor[20005];int phi[N];void init(){    for(int i=0;i<N;i++)        phi[i]=i;    for(int i=2;i<N;i++)    {        if(phi[i]==i)        {            for(int j=i;j<N;j+=i)                phi[j]-=phi[j]/i;        }    }    for(int i=1;i<=20000;i++)        for(int j=i;j<=20000;j+=i)        factor[j].push_back(i);}int block[N];struct node{    int l,r;    int index;}query[N];ll ans[N];int a[N];int cmp(node x1,node x2){    if(block[x1.l]==block[x2.l])        return x1.r<x2.r;    return block[x1.l]<block[x2.l];}int cnt[N];int curL,curR;ll curAns;void add(int x){    for(int i=0;i<factor[x].size();i++)        {            int num=factor[x][i];            curAns+=phi[num]*cnt[num];            cnt[num]++;        }}void sub(int x){    for(int i=0;i<factor[x].size();i++)        {            int num=factor[x][i];            cnt[num]--;            curAns-=phi[num]*cnt[num];        }}void work(int L,int R){    while(curL<L)    {        sub(a[curL]);        curL++;    }    while(curL>L)    {        curL--;        add(a[curL]);    }    while(curR>R)    {        sub(a[curR]);        curR--;    }    while(curR<R)    {        curR++;        add(a[curR]);    }}int main(){    init();    int t,n;    scanf("%d",&t);    int cal=1;    while(t--)    {        memset(cnt,0,sizeof(cnt));        scanf("%d",&n);        int limit=(int)sqrt(n);        for(int i=1;i<=n;i++)            block[i]=(i-1)/limit;        for(int i=1;i<=n;i++)            scanf("%d",a+i);        int m;        scanf("%d",&m);        for(int i=1;i<=m;i++)        {            scanf("%d%d",&query[i].l,&query[i].r);            query[i].index=i;        }        sort(query+1,query+1+m,cmp);        curAns=0;        for(int i=query[1].l;i<=query[1].r;i++)            add(a[i]);        ans[query[1].index]=curAns;        curL=query[1].l;        curR=query[1].r;        for(int i=2;i<=m;i++)        {            work(query[i].l,query[i].r);            ans[query[i].index]=curAns;        }        printf("Case #%d:\n",cal++);        for(int i=1;i<=m;i++)            printf("%lld\n",ans[i]);    }    return 0;}

智障的版本:

#include<cstdio>#include<iostream>#include<algorithm>#include<cstring>#include<cmath>#include<bitset>#include<vector>#define N 20500#define INF 10000000000#define mod 1000000007using namespace std;typedef long long  ll;vector<int> prime;int phi[N];void init(){    for(int i=0;i<N;i++)        phi[i]=i;    for(int i=2;i<N;i++)    {        if(phi[i]==i)        {            prime.push_back(i);            for(int j=i;j<N;j+=i)                phi[j]-=phi[j]/i;        }    }}int block[N];struct node{    int l,r;    int index;}query[N];int ans[N];int a[N];int cmp(node x1,node x2){    if(block[x1.l]==block[x2.l])        return x1.r<x2.r;    return block[x1.l]<block[x2.l];}int gcd(int a,int b){    return a%b==0?b:gcd(b,a%b);}int cnt[N];int curAns,curL,curR;int fac[100];int e[100];int k;void getFac(int x){    k=0;    for(int i=0;prime[i]*prime[i]<=x;i++)    {        if(x%prime[i]==0)        {            fac[k]=prime[i];            e[k]=0;            while(x%prime[i]==0)            {                x/=prime[i];                e[k]++;            }            k++;        }    }    if(x>1)    {        fac[k]=x;        e[k]=1;        k++;    }}int state;void dfs(int cur,int temp){    if(cur==k)    {        //cout<<temp<<endl;        if(state==0)        {            cnt[temp]--;            curAns-=phi[temp]*cnt[temp];        }        else        {            curAns+=phi[temp]*cnt[temp];            cnt[temp]++;        }        return ;    }    dfs(cur+1,temp);    int c=temp;    for(int i=1;i<=e[cur];i++)    {        c*=fac[cur];        dfs(cur+1,c);    }}void dfs2(int cur,int temp){    if(cur==k)    {        cnt[temp]++;        return ;    }    dfs2(cur+1,temp);    int c=temp;    for(int i=1;i<=e[cur];i++)    {        c*=fac[cur];        dfs2(cur+1,c);    }}void work(int L,int R){    while(curL<L)    {        state=0;        getFac(a[curL]);        dfs(0,1);        curL++;    }    while(curL>L)    {        state=1;        curL--;        getFac(a[curL]);        dfs(0,1);    }    while(curR>R)    {        state=0;        getFac(a[curR]);        dfs(0,1);        curR--;    }    while(curR<R)    {        state=1;        curR++;        getFac(a[curR]);        dfs(0,1);    }}int main(){    init();    int t,n;    scanf("%d",&t);    int cal=1;    while(t--)    {        memset(cnt,0,sizeof(cnt));        scanf("%d",&n);        int limit=(int)sqrt(n);        for(int i=1;i<=n;i++)            block[i]=(i-1)/limit;        for(int i=1;i<=n;i++)            scanf("%d",a+i);        int m;        scanf("%d",&m);        for(int i=1;i<=m;i++)        {            scanf("%d%d",&query[i].l,&query[i].r);            query[i].index=i;        }        sort(query+1,query+1+m,cmp);        curAns=0;        for(int i=query[1].l;i<=query[1].r;i++)        {            getFac(a[i]);            dfs2(0,1);            for(int j=i+1;j<=query[1].r;j++)                curAns+=gcd(a[i],a[j]);        }        ans[query[1].index]=curAns;        curL=query[1].l;        curR=query[1].r;        for(int i=2;i<=m;i++)        {            work(query[i].l,query[i].r);            //cout<<curL<<" "<<curR<<endl;            /*for(int i=1;i<=5;i++)                cout<<cnt[i]<<" ";            cout<<endl;*/            ans[query[i].index]=curAns;        }        printf("Case #%d:\n",cal++);        for(int i=1;i<=m;i++)            printf("%d\n",ans[i]);    }    return 0;}
原创粉丝点击