【HDU4947】GCD Array (莫比乌斯反演+树状数组)
BUPT2017 wintertraining(15) #5H
题意
有一个长度为l的数组,现在有m个操作,第1种为1 n d v,给下标x 满足gcd(x,n)=d的\(a_x\)增加v。第2种为2 x,查询\(\sum_{i=1}^x a_i\)。
数据范围:\(1\le n,d,v\le2\cdot 10^5,1\le x\le l\)
题解
设\(f_i\)满足\(a_i=\sum_{d|i} f_d\),用树状数组存储\(f_i\)的前缀和。
\]
根据莫比乌斯函数(关于莫比乌斯反演可以看这篇论文:贾志鹏线性筛法与积性函数)的性质,我们知道\(\sum_{d|n}\mu(d)=[n=1]\),(这个d和上面的d不是同一个,下面换为p表示) 因此
\]
于是对于给定的n和d,\(\frac n d\)的因子p的d倍就是符合条件的下标x的一个因子。
莫比乌斯反演可得:
\(f(n)=\sum_{d|n}\mu(\frac n d)a(n)\)
因此\(f_{pd}=\sum \mu(p)a(pd)\),于是对于1操作,我们只要给\(f_{pd}\)加上\(v\cdot \mu (p)\)即可。
2操作,是对\(a_i\)求和:
\]
对于固定的d来说,1~x内\(f_d\)要加\(\lfloor \frac x d\rfloor\)次。再分块加速一下,也就是对于\(\lfloor\frac x d\rfloor\)相同的d,把\(f_d\)区间和求出来再乘上\(\lfloor\frac x d\rfloor\),设这个区间是[d1,d2],那么d2=x/(x/d1) (整除),为什么呢?因为d2是满足\(\frac x d \ge \lfloor \frac x {d1}\rfloor=k\)的最大的整数d,那么\(x\ge d2\cdot k\),所以\(\frac x k \ge d2\),也就是d2=\(\lfloor\frac x k\rfloor\)。
这题的时间复杂度:
预处理出1~N的所有因子,\(O(n\sqrt n)\)。
计算莫比乌斯函数,\(O(n)\)。
1操作,因子有\(\sqrt n\)个,增加是\(O(\log n)\),总的是\(O(m\sqrt n \log n)\)。
2操作,查询\(O(log n)\),分块\(O(\sqrt n)\),也是\(O(m\sqrt n \log n)\)。
总的就是\(O(m\sqrt n \log n)\)
官方题解:
代码
#include<cstdio>
#include<cstring>
#include<vector>
#define ll long long
#define N 200005
using namespace std;
int miu[N],prime[N],cnt;
ll sum[N],last,lasttemp,temp;
vector<int>fac[N];
bool check[N];
ll ans;
ll getsum(int x){
ll ans=0;
for(;x;x-=x&-x)ans+=sum[x];
return ans;
}
void add(int x,int v){
for(;x<N;x+=x&-x)sum[x]+=v;
}
void Mobius(){
miu[1]=1;
for(int i=2;i<N;i++){
if(!check[i]){
prime[cnt++]=i;
miu[i]=-1;
}
for(int j=0;j<cnt;j++){
if(i*prime[j]>N)break;
check[i*prime[j]]=1;
if(i%prime[j])miu[i*prime[j]]=-miu[i];
else break;
}
}
}
int main(){
int l,m,cas=0;
Mobius();
for(int i=1;i<N;i++)
for(int j=i;j<N;j+=i)
fac[j].push_back(i);
while(scanf("%d%d",&l,&m),l,m){
printf("Case #%d:\n",++cas);
memset(sum,0,sizeof sum);
while(m--){
int n,d,v,x;
scanf("%d",&n);
if(n==1){
scanf("%d%d%d",&n,&d,&v);
if(n%d)continue;
n/=d;
for(int i=0;i<fac[n].size();i++){
x=fac[n][i];
add(x*d,miu[x]*v);
}
}else{
scanf("%d",&n);
ans=temp=0;
for(int i=1;i<=n;i=last+1){
last=n/(n/i);
lasttemp=temp;
temp=getsum(last);
ans+=n/i*(temp-lasttemp);
}
printf("%lld\n",ans);
}
}
}
}
待看的文章:读贾志鹏线性筛有感 (莫比乌斯函数的应用)
【HDU4947】GCD Array (莫比乌斯反演+树状数组)的更多相关文章
- 【HDU4947】GCD Array(莫比乌斯反演+树状数组)
点此看题面 大致题意: 一个长度为\(n\)的数组,实现两种操作:将满足\(gcd(i,k)=d\)的\(a_i\)加上\(v\),询问\(\sum_{i=1}^xa_i\). 对于修改操作的推式子 ...
- HDU4947GCD Array(莫比乌斯反演+树状数组)
题面 传送门 题解 orz ljz 相当于每一个数要加上 \[v\times [\gcd(i,n)=d]=v\times [\gcd(i/d,n/d)=1]=v\times \sum_{p|{i\ov ...
- BZOJ 3259 [Sdoi2014]数表 (莫比乌斯反演 + 树状数组)
3529: [Sdoi2014]数表 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 2321 Solved: 1187[Submit][Status ...
- 【BZOJ3529】[Sdoi2014]数表 莫比乌斯反演+树状数组
[BZOJ3529][Sdoi2014]数表 Description 有一张N×m的数表,其第i行第j列(1 < =i < =礼,1 < =j < =m)的数值为能同时整除i和 ...
- BZOJ 3529 [Sdoi2014]数表 (莫比乌斯反演+树状数组+离线)
题目大意:有一张$n*m$的数表,第$i$行第$j$列的数是同时能整除$i,j$的所有数之和,求数表内所有不大于A的数之和 先是看错题了...接着看对题了发现不会做了...刚了大半个下午无果 看了Po ...
- BZOJ 3529: [Sdoi2014]数表 [莫比乌斯反演 树状数组]
3529: [Sdoi2014]数表 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 1399 Solved: 694[Submit][Status] ...
- 洛谷P3312 [SDOI2014]数表(莫比乌斯反演+树状数组)
传送门 不考虑$a$的影响 设$f(i)$为$i$的约数和 $$ans=\sum\limits_{i=1}^n\sum\limits_{j=1}^nf(gcd(i,j))$$ $$=\sum\limi ...
- BZOJ 3529 [Sdoi2014]数表 ——莫比乌斯反演 树状数组
$ans=\sum_{i=1}^n\sum_{j=1}^n\sigma(gcd(i,j))$ 枚举gcd为d的所有数得到 $ans=\sum_{d<=n}\sigma(d)*g(d)$ $g(d ...
- 【BZOJ3529】【莫比乌斯反演 + 树状数组】[Sdoi2014]数表
Description 有一张N×m的数表,其第i行第j列(1 < =i < =礼,1 < =j < =m)的数值为 能同时整除i和j的所有自然数之和.给定a,计算数表中不大于 ...
随机推荐
- iOS原生实现二维码拉近放大
http://www.cocoachina.com/ios/20180416/23033.html 2018-04-16 15:34 编辑: yyuuzhu 分类:iOS开发 来源:程序鹅 8 300 ...
- 百度地图支持https
百度地图SDK, 支持https <script src="http://api.map.baidu.com/api?v=3.0&ak=nbnttGGI6lilllgy2zn ...
- 使用 Drools 和 JPA & Drools show case in docker hub
使用 Drools 和 JPA 实现持续的实时数据分析https://www.ibm.com/developerworks/cn/java/j-drools5/index.html Drools - ...
- JEECG & JEESite Tomcat集群 Session共享
多台tomcat服务的session共享 memcached与redis - JEECG开源社区 - CSDN博客https://blog.csdn.net/zhangdaiscott/article ...
- Redis教程(Linux)
这里汇总了从简单的安装到较为复杂的配置,由浅入深的学习redis... 一 , 安装 1) redis扩展安装 从官网上下载扩展压缩包 wget http://pecl.php.net/get/red ...
- day 7-18 mysql case when语句
概述: sql语句中的case语句与高级语言中的switch语句,是标准sql的语法,适用于一个条件判断有多种值的情况下分别执行不同的操作. 首先,让我们看一下CASE的语法.在一般的SELECT中, ...
- linux之ssh互信
1.如果你是之作root用户互信的话,直接一路执行如下命令就行. 1.切换你需要互信的账户 su hadoop1 2.执行命令,一路回车即可(在当前用的宿主用户目录下的.ssh目录下生成公钥和秘钥id ...
- systemd取消对服务重启的限制
默认情况下,一个服务在10秒内最多允许启动5次.当超过5次后,会报如下错误: Job for xx.service failed because start of the service was at ...
- /dev被异常删除的问题
今天遇到一个问题,在执行某些操作后,发现经常报“read_urandom: /dev/urandom: open failed: No such file or directory”这个错误.后来查看 ...
- python数学第三天【方向导数】
1.方向导数 2. 梯度 3. 凸函数: 4. 凸函数的判定 5. 凸函数的一般表示 6. 凸性质的应用