首页 > 代码库 > BZOJ3853: GCD Array

BZOJ3853: GCD Array

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=3853

题解:我们发现直接修改是肯定不行的。因为一次有可能修改的很多。而且编号也是不连续的。

搬运题解:

{

注意到给所有gcd(x,n)==d的数加上v等价于给每个数加上[gcd(x,n)==d]*v,而我们可以发现:

[gcd(x,n)==d]*v => 

[gcd(x/d,n/d)==1] *v=> 

sigma(mu[q] * v) (q | n/d && q | x/d)

=> sigma(mu[q] * v) (q | n/d && q*d | x)  

 其中mu是莫比乌斯函数

我们可以构造一个数组f,让a[i] == sigma(f[j]) (j | i),然后修改操作就变成了:对所有满足条件的q,让f[q*d]加上mu[q] * v,那么根据f数组的性质,我们每个a[i]就能很顺利的加上[gcd(x,n)==d]*v了。

}

其实这相当与我们把修改和查询都往前推了一下,推到了一个公共的部分,然后发现这个部分维护所需时间在允许范围内。so。。。

这题的思想还需要领悟。。。

代码:

技术分享
  1 #include<cstdio>  2   3 #include<cstdlib>  4   5 #include<cmath>  6   7 #include<cstring>  8   9 #include<algorithm> 10  11 #include<iostream> 12  13 #include<vector> 14  15 #include<map> 16  17 #include<set> 18  19 #include<queue> 20  21 #include<string> 22  23 #define inf 1000000000 24  25 #define maxn 200000 26  27 #define maxm 200000+5 28  29 #define eps 1e-10 30  31 #define ll long long 32  33 #define pa pair<int,int> 34  35 #define for0(i,n) for(int i=0;i<=(n);i++) 36  37 #define for1(i,n) for(int i=1;i<=(n);i++) 38  39 #define for2(i,x,y) for(int i=(x);i<=(y);i++) 40  41 #define for3(i,x,y) for(int i=(x);i>=(y);i--) 42  43 #define for4(i,x) for(int i=head[x],y=e[i].go;i;i=e[i].next,y=e[i].go) 44  45 #define for5(n,m) for(int i=1;i<=n;i++)for(int j=1;j<=m;j++) 46  47 #define mod 1000000007 48  49 using namespace std; 50  51 inline int read() 52  53 { 54  55     int x=0,f=1;char ch=getchar(); 56  57     while(ch<0||ch>9){if(ch==-)f=-1;ch=getchar();} 58  59     while(ch>=0&&ch<=9){x=10*x+ch-0;ch=getchar();} 60  61     return x*f; 62  63 } 64 int n,m,mu[maxn+1],p[maxn],tot; 65 ll s[maxn]; 66 bool v[maxn+1]; 67 vector<int>fac[maxn+1]; 68 inline void add(int x,int y) 69 { 70     for(;x<=n;x+=x&(-x))s[x]+=y; 71 } 72 inline ll sum(int x) 73 { 74     ll t=0; 75     for(;x;x-=x&(-x))t+=s[x]; 76     return t; 77 } 78 inline void get() 79 { 80     mu[1]=1; 81     for2(i,2,maxn) 82     { 83         if(!v[i])p[++tot]=i,mu[i]=-1; 84         for1(j,tot) 85         { 86             int k=i*p[j]; 87             if(k>maxn)break; 88             v[k]=1; 89             if(i%p[j])mu[k]=-mu[i]; 90             else {mu[k]=0;break;} 91         } 92         //cout<<i<<‘ ‘<<mu[i]<<endl; 93     } 94     for1(i,maxn) 95      for(int j=i;j<=maxn;j+=i) 96       fac[j].push_back(i); 97 } 98  99 int main()100 101 {102 103     freopen("input.txt","r",stdin);104 105     freopen("output.txt","w",stdout);106     get();107 108     for1(cs,inf)109     {110         n=read();m=read();111         if(!n&&!m)break;112         printf("Case #%d:\n",cs);113         memset(s,0,sizeof(s));114         while(m--)115         {116             int op=read();117             if(op==1)118             {119                 int x=read(),y=read(),z=read();120                 if(x%y)continue;121                 x/=y;122                 for3(i,fac[x].size()-1,0)add(fac[x][i]*y,mu[fac[x][i]]*z);123             }else124             {125                 int t=read();ll ans=0;126                 for(int i=1,j;i<=t;i=j+1)127                 {128                     j=t/(t/i);129                     ans+=(ll)t/i*(sum(j)-sum(i-1));130                 }131                 printf("%lld\n",ans);132             }133         }134     }135 136     return 0;137 138 }  
View Code

 

 

 

 

BZOJ3853: GCD Array