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

 

 

 

posted @ 2013-08-16 19:48  _随心所欲_  阅读(684)  评论(2编辑  收藏  举报