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             }else
124             {
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 }  

时间: 2024-10-06 00:23:39

BZOJ3853: GCD Array的相关文章

HDU 4947 GCD Array

GCD Array Time Limit: 11000/5500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 843    Accepted Submission(s): 205 Problem Description Teacher Mai finds that many problems about arithmetic function can be reduced to

【莫比乌斯反演+树状数组+分块求和】GCD Array

https://www.bnuoj.com/v3/contest_show.php?cid=9149#problem/I [题意] 给定长度为l的一个数组,初始值为0:规定了两种操作: [思路] 找到了一个讲解很清楚的博客http://www.cnblogs.com/flipped/p/HDU4947.html [Accepted] 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #inc

51Nod 算法马拉松15 记一次悲壮而又开心的骗分比赛

OwO 故事的起源大概是zcg前天发现51Nod晚上有场马拉松,然后他就很开心的过去打了 神奇的故事就开始了: 晚上的时候我当时貌似正在写线段树?然后看见zcg一脸激动告诉我第一题有九个点直接输出B就可以A.. 然后之后zcg以奇怪的二分方式发现了如何A掉第一题的第十个点(我记得貌似是什么第5000个数等于511? OwO 就这样没有任何思考含量全凭骗分黑科技过掉了第一题 OwO 然后zcg打开了第二题,发现第二题样例有点问题,然后就发了个帖子,直接去看第三题了 我去瞅了一眼,发现这不是gcd

【CodeForces 624D】Array GCD

题 You are given array ai of length n. You may consecutively apply two operations to this array: remove some subsegment (continuous subsequence) of length m < n and pay for it m·a coins; change some elements of the array by at most 1, and pay b coins

Array GCD CodeForces - 624D (dp,gcd)

大意: 给定序列, 给定常数a,b, 两种操作, (1)任选一个长为$t$的子区间删除(不能全部删除), 花费t*a. (2)任选$t$个元素+1/-1, 花费t*b. 求使整个序列gcd>1的最少花费. 题目有个限制是不能全部删除, 所以最后一定剩余a[1]或a[n], 暴力枚举a[1]与a[n]的所有素因子即可. 这场div. 2题目感觉都挺简单的, 但实现起来各种出错...........各种细节还是没考虑好...... #include <iostream> #include &

转 GCD

GCD 深入理解:第一部分 本文翻译自 http://www.raywenderlich.com/60749/grand-central-dispatch-in-depth-part-1 原作者:Derek Selander 译者:@nixzhu 虽然 GCD 已经出现过一段时间了,但不是每个人都明了其主要内容.这是可以理解的:并发一直很棘手,而 GCD 是基于 C 的 API ,它们就像一组尖锐的棱角戳进 Objective-C 的平滑世界.我们将分两个部分的教程来深入学习 GCD . 在这两

OC多线程之GCD ----- 2

dispatch_create生成的Queue不管是并行队列还是串行队列,其优先级都是默认优先级 但是可以用dispatch_set_target_queue来改变队列的优先级 dispatch_set_target_queue(原来的队列, 目标优先级队列) 使用这个函数需要获取两个队列,一个是需要变更优先级的队列,一个是指定优先级的队列(指定优先级的队列可以通过get_global获得) 如果多个串行队列优先级相同,那么这些队列里的任务也会串行执行 dispatch_after函数并不能非常

GCD - 多线程

什么是 GCD GCD 是 libdispatch 的市场名称,而 libdispatch 作为 Apple 的一个库,为并发代码在多核硬件(跑 iOS 或 OS X )上执行提供有力支持.它具有以下优点: 1.GCD 能通过推迟昂贵计算任务,并在后台运行它们改善应用的响应性能. 2.GCD 提供一个易于使用的并发模型而不仅仅只是锁和线程,以帮助我们避开并发陷阱. 3.GCD 具有在常见模式(例如单例),用更高性能的原语优化你的代码. GCD 术语 Serial vs. Concurrent 串

GCD详解

一.GCD的优势 1.GCD是苹果公司为多核的并行运算提出的解决方案. 2.GCD会自动利用更多的CPU内核(比如双核.四核). 3.GCD会自动管理线程的生命周期(创建线程.调度任务.销毁线程). 二.GCD有两个核心概念 1.任务 2.队列 三.使用CGD的步骤 1.定制任务 2.将任务添加到队列中,CGD会自动将队列中的任务取出,放到对应的线程中执行.任务的取出遵循队列的FIFD原则,先进先出,后进后出. 四.同步和异步的区别 1.同步只能在当前线程中执行任务,不具备开启新线程的能力 2.