【HDU4676】Sum Of Gcd-莫队算法+欧拉函数
2018-02-23 17:44
525 查看
测试地址:Sum Of Gcd
题目大意:给定一个11~nn的全排列AA,若干个询问,每次询问给出一个区间[l,r][l,r],要求得出∑l≤i<j≤rgcd(Ai,Aj)∑l≤i<j≤rgcd(Ai,Aj)的值。
做法:本题需要用到莫队算法+欧拉函数。
我们不好直接统计各个数对的最大公约数出现的次数,但是我们可以比较简单地统计各个数对的公约数出现的次数。由于数对的公约数都是数对最大公约数的约数(有点绕……),我们很自然地思考一个数和它的约数之间有什么容易统计的关系。
我们可以用一个结论将一个数字和它的约数建立统计关系:
n=∑d|nφ(d)n=∑d|nφ(d)
那么有:
∑l≤i<j≤rgcd(Ai,Aj)∑l≤i<j≤rgcd(Ai,Aj)
=∑l≤i<j≤r∑d|gcd(Ai,Aj)φ(d)=∑l≤i<j≤r∑d|gcd(Ai,Aj)φ(d)
=∑nd=1φ(d)∑l≤i<j≤r[d|Ai][d|Aj]=∑d=1nφ(d)∑l≤i<j≤r[d|Ai][d|Aj]
显然式子中的∑l≤i<j≤r[d|Ai][d|Aj]∑l≤i<j≤r[d|Ai][d|Aj]就是指dd作为区间内数对的公约数出现的次数。而统计每个数作为公约数出现的次数的方法就很简单了,你只需要统计每个数ii是区间内多少个数的约数,令这个数值为cnticnti,那么它作为公约数出现的次数就是cnti(cnti−1)2cnti(cnti−1)2,这样就将问题转化为了对区间内所有数的约数出现的次数的统计。
接下来我们就可以用莫队算法解决了。我们预先处理出所有数的所有约数以及欧拉函数,然后每新增或删除一个元素,对它的所有约数更新cntdcntd。很显然,对于一个约数dd,在新增一个元素时,答案增加(cntd−1)φ(d)(cntd−1)φ(d),在删除一个元素时,答案减少cntdφ(d)cntdφ(d),注意这里的cntdcntd是更新后的值。每新增或删除一个元素的复杂度大概在O(logn)O(logn)左右,所以总的时间复杂度是O(nn−−√logn)O(nnlogn),可以通过此题。
(最近在学习分块,据说莫队算法是分块的一种,所以也做一道题吧……)
以下是本人代码:
题目大意:给定一个11~nn的全排列AA,若干个询问,每次询问给出一个区间[l,r][l,r],要求得出∑l≤i<j≤rgcd(Ai,Aj)∑l≤i<j≤rgcd(Ai,Aj)的值。
做法:本题需要用到莫队算法+欧拉函数。
我们不好直接统计各个数对的最大公约数出现的次数,但是我们可以比较简单地统计各个数对的公约数出现的次数。由于数对的公约数都是数对最大公约数的约数(有点绕……),我们很自然地思考一个数和它的约数之间有什么容易统计的关系。
我们可以用一个结论将一个数字和它的约数建立统计关系:
n=∑d|nφ(d)n=∑d|nφ(d)
那么有:
∑l≤i<j≤rgcd(Ai,Aj)∑l≤i<j≤rgcd(Ai,Aj)
=∑l≤i<j≤r∑d|gcd(Ai,Aj)φ(d)=∑l≤i<j≤r∑d|gcd(Ai,Aj)φ(d)
=∑nd=1φ(d)∑l≤i<j≤r[d|Ai][d|Aj]=∑d=1nφ(d)∑l≤i<j≤r[d|Ai][d|Aj]
显然式子中的∑l≤i<j≤r[d|Ai][d|Aj]∑l≤i<j≤r[d|Ai][d|Aj]就是指dd作为区间内数对的公约数出现的次数。而统计每个数作为公约数出现的次数的方法就很简单了,你只需要统计每个数ii是区间内多少个数的约数,令这个数值为cnticnti,那么它作为公约数出现的次数就是cnti(cnti−1)2cnti(cnti−1)2,这样就将问题转化为了对区间内所有数的约数出现的次数的统计。
接下来我们就可以用莫队算法解决了。我们预先处理出所有数的所有约数以及欧拉函数,然后每新增或删除一个元素,对它的所有约数更新cntdcntd。很显然,对于一个约数dd,在新增一个元素时,答案增加(cntd−1)φ(d)(cntd−1)φ(d),在删除一个元素时,答案减少cntdφ(d)cntdφ(d),注意这里的cntdcntd是更新后的值。每新增或删除一个元素的复杂度大概在O(logn)O(logn)左右,所以总的时间复杂度是O(nn−−√logn)O(nnlogn),可以通过此题。
(最近在学习分块,据说莫队算法是分块的一种,所以也做一道题吧……)
以下是本人代码:
#include <bits/stdc++.h> #define ll long long using namespace std; int T,n,m,blocklen,block[20010],a[20010],fac[20010][210]; ll phi[20010],p[20010],cnt[20010],ans[20010],sum; bool prime[20010]={0}; struct Query { int id,l,r; }q[20010]; void calc_phi() { prime[1]=1;p[0]=0; for(int i=1;i<=20000;i++) phi[i]=1; for(int i=2;i<=20000;i++) { if (!prime[i]) phi[i]=i-1,p[++p[0]]=i; for(int j=1;j<=p[0]&&i*p[j]<=20000;j++) { prime[i*p[j]]=1; if (i%p[j]==0) {phi[i*p[j]]=phi[i]*p[j];break;} phi[i*p[j]]=phi[i]*(p[j]-1); } } } bool cmp(Query a,Query b) { if (block[a.l]!=block[b.l]) return block[a.l]<block[b.l]; else return a.r<b.r; } void expand(int x,ll add) { for(int i=1;i<=fac[a[x]][0];i++) { int j=fac[a[x]][i]; if (add==1) sum+=cnt[j]*phi[j]; else sum-=(cnt[j]-1)*phi[j]; cnt[j]+=add; } } void Mo() { int l=1,r=0; memset(cnt,0,sizeof(cnt)); sum=0; for(int i=1;i<=m;i++) { while (q[i].l<l) expand(--l,1); while (q[i].r>r) expand(++r,1); while (q[i].l>l) expand(l++,-1); while (q[i].r<r) expand(r--,-1); ans[q[i].id]=sum; } } int main() { scanf("%d",&T); calc_phi(); for(int i=1;i<=20000;i++) { fac[i][0]=0; for(int j=1;j*j<=i;j++) if (i%j==0) { fac[i][++fac[i][0]]=j; if (j*j!=i) fac[i][++fac[i][0]]=i/j; } } int t=1; while(T--) { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); scanf("%d",&m); blocklen=(int)sqrt(n); for(int i=1;i<=n;i++) block[i]=i/blocklen; for(int i=1;i<=m;i++) { scanf("%d%d",&q[i].l,&q[i].r); q[i].id=i; } sort(q+1,q+m+1,cmp); Mo(); printf("Case #%d:\n",t); for(int i=1;i<=m;i++) printf("%lld\n",ans[i]); t++; } return 0; }
相关文章推荐
- hdu 5381 The sum of gcd 原来有个算法叫莫队 2015 Multi-University Training Contest 8
- HDOJ 5381 The sum of gcd 莫队算法
- HDU 5381 The sum of gcd 莫队算法
- HDU 5381(The sum of gcd-莫队算法解决区间段gcd的和)
- HDOJ 5381 The sum of gcd 莫队算法
- HDU 5381 The sum of gcd 询问区间内所有子区间的GCD和 [莫队算法]
- hdu5381 The sum of gcd]莫队算法
- [反演 莫队算法] HDU 4676 Sum Of Gcd
- HDU 5381 The sum of gcd (技巧,莫队算法)
- [数论 反演 && 莫队] hdu4676 . Sum Of Gcd
- hdu 5381 The sum of gcd 莫队 + DP
- hdu4676 Sum Of Gcd
- HDU4676 Sum Of Gcd
- HDU4676 Sum Of Gcd (数论 + 分块)
- Sum Of Gcd HDU - 4676(莫队)
- HDU 4676 Sum Of Gcd(欧拉函数求区间gcd之和+分块算法)
- [莫比乌斯反演+莫队] HDU4676 Sum Of Gcd
- hdu 5381 The sum of gcd 莫队+预处理
- [数论][莫队][莫比乌斯反演] hdu 4676 Sum Of Gcd
- HDU 5381 The sum of gcd 莫队暴力