hdu 4676 Sum Of Gcd

离线+分块!!

思路:序列a[1],a[2],a[3]……a[n]

num[i]表示区间[L,R]中是i的倍数的个数;euler[i]表示i的欧拉函数值。

则区间的GCD之和sum=∑(C(num[i],2)*euler[i]).当增加一个数时,若有约数j,则只需加上num[j]*euler[j],之后再num[j]++;

反之亦然!!

代码如下:

 

  1 #include<iostream>

  2 #include<stdio.h>

  3 #include<algorithm>

  4 #include<iomanip>

  5 #include<cmath>

  6 #include<cstring>

  7 #include<vector>

  8 #define ll __int64

  9 #define pi acos(-1.0)

 10 #define MAX 20002

 11 using namespace std;

 12 int R,L,an[MAX],euler[MAX],ans[MAX],res,num[MAX];

 13 bool vis[MAX],prime[MAX];

 14 struct node

 15 {

 16     int x,y,l,p;

 17 }q[MAX];

 18 vector<int>p[MAX];

 19 void init()//初始化欧拉函数值

 20 {

 21     int i,j;

 22     for(i=1;i<MAX;i++) euler[i]=i;

 23     for(i=2;i<MAX;i++)

 24     if(euler[i]==i){

 25         for(j=i;j<MAX;j+=i)

 26             euler[j]=euler[j]/i*(i-1);

 27     }

 28 }

 29 void factor(int n)//分解因子

 30 {

 31     p[n].clear();

 32     for(int i=1;i*i<=n;i++){

 33         if(n%i==0){

 34             p[n].push_back(i);

 35             if(i*i!=n) p[n].push_back(n/i);

 36         }

 37     }

 38 }

 39 bool cmp(const node &a,const node &b)

 40 {

 41     if(a.l==b.l) return a.y<b.y;

 42     return a.l<b.l;

 43 }

 44 void query(int x,int y,int flag)//查询操作

 45 {

 46     int t;

 47     if(flag){

 48         for(int i=x;i<L;i++){

 49             for(int j=0;j<p[an[i]].size();j++){

 50                 t=p[an[i]][j];

 51                 res+=num[t]*euler[t];

 52                 num[t]++;

 53             }

 54         }

 55         for(int i=L;i<x;i++){

 56             for(int j=0;j<p[an[i]].size();j++){

 57                 t=p[an[i]][j];

 58                 num[t]--;

 59                 res-=num[t]*euler[t];

 60             }

 61         }

 62         for(int i=y+1;i<=R;i++){

 63             for(int j=0;j<p[an[i]].size();j++){

 64                 t=p[an[i]][j];

 65                 num[t]--;

 66                 res-=num[t]*euler[t];

 67             }

 68         }

 69         for(int i=R+1;i<=y;i++){

 70             for(int j=0;j<p[an[i]].size();j++){

 71                 t=p[an[i]][j];

 72                 res+=num[t]*euler[t];

 73                 num[t]++;

 74             }

 75         }

 76     }

 77     else{

 78         for(int i=x;i<=y;i++){

 79             for(int j=0;j<p[an[i]].size();j++){

 80                 t=p[an[i]][j];

 81                 res+=num[t]*euler[t];

 82                 num[t]++;

 83             }

 84         }

 85     }

 86     L=x;R=y;

 87 }

 88 int main(){

 89     int n,t,i,j,m,c,ca=0;

 90     init();

 91     for(i=1;i<=20000;i++) factor(i);

 92     scanf("%d",&c);

 93     while(c--){

 94         scanf("%d",&n);

 95         for(i=1;i<=n;i++) scanf("%d",&an[i]);

 96         m=sqrt(1.0*n);

 97         scanf("%d",&t);

 98         for(i=0;i<t;i++){

 99             scanf("%d%d",&q[i].x,&q[i].y);

100             q[i].l=q[i].x/m;

101             q[i].p=i;

102         }

103         sort(q,q+t,cmp);

104         res=0;

105         memset(num,0,sizeof(num));

106         for(i=0;i<t;i++){

107             query(q[i].x,q[i].y,i);

108             ans[q[i].p]=res;

109         }

110         printf("Case #%d:\n",++ca);

111         for(i=0;i<t;i++)

112             printf("%d\n",ans[i]);

113     }

114     return 0;

115 }
View Code

 

 

 

你可能感兴趣的:(HDU)