【题解】震惊!!!GCD SUM套路竟狂水七倍经验!!!

标题党又来了

题目描述

给定 n n n,求 ∑ i = 1 n ∑ j = i + 1 n g c d ( i , j ) \sum\limits_{i=1}^{n} \sum\limits_{j=i+1}^{n}gcd(i,j) i=1nj=i+1ngcd(i,j)


解法1:暴力

两个for搞定。每一次计算复杂度为 O ( n 2 ) ​ O(n^2)​ O(n2)

于是你可以水掉UVA11417

解法2:化柿子

既然直接枚举 i , j ​ i,j​ i,j不行,那么我们换成枚举 g c d ​ gcd​ gcd,假设我们已经确定了 i , j ​ i,j​ i,j g c d ​ gcd​ gcd k ​ k​ k,那么 g c d ( i / k , j / k ) = 1 ​ gcd(i/k,j/k)=1​ gcd(i/k,j/k)=1,于是问题转化为,在 [ 1 , ⌊ n k ⌋ ] ​ [1,\lfloor \frac{n}{k} \rfloor]​ [1,kn]范围内,互质的无序数对个数。

我们接着转化,假设我们已经知道了互质的数中的较大的一个 a a a,那么我们要做的就是求出小于这个数的与它互质的数。想到了什么?欧拉函数!!

于是我们会发现,我们要求的就是在 [ 1 , ⌊ n k ⌋ ] [1,\lfloor \frac{n}{k} \rfloor] [1,kn]范围内的所有数的欧拉函数值得和。

那么最终的答案就是
∑ k = 1 n ∑ d = 1 ⌊ n k ⌋ ϕ ( d ) \sum_{k=1}^{n} \sum_{d=1}^{\lfloor\frac{n}{k}\rfloor}\phi(d) k=1nd=1knϕ(d)
然后我们发现,后面一个和可以通过线性筛和前缀和预处理做到 O ( 1 ) O(1) O(1)查询和。于是成功的把每次计算复杂度降到了 O ( n ) ​ O(n)​ O(n)

于是你可以*掉洛谷1390洛谷2398,还有洛谷2568

不过要注意的是,这些题中的 ϕ ( 1 ) ​ \phi(1)​ ϕ(1)的初始值会有所不同,并且有些题求的是有序数对个数,需要对答案进行一些简单处理。

终极解法:统统预处理

尽管解法2已经将时间复杂度压到了一次计算 O ( n ) ​ O(n)​ O(n),几乎是最优了,但对于多组数据,尤其是几万甚至几十万的数据组数时,就显得太慢了愚蠢,垃圾

我们发现, O ( n ) O(n) O(n)复杂度的瓶颈在于每次都需要枚举计算。那么我们考虑用预处理把所有的答案都预处理出来,做到 O ( 1 ) O(1) O(1)查询。

继续化柿子:
设 f ( n ) = ∑ i = 1 n − 1 g c d ( i , n ) 那 么 a n s = ∑ i = 1 n f ( n ) f ( n ) = ∑ d ∣ n d × ∑ i = 1 n − 1 [ g c d ( i , n ) = d ] = ∑ d ∣ n d × ∑ i = 1 n d − 1 [ g c d ( i , n d ) = 1 ] = ∑ d ∣ n d × ϕ ( n d ) \begin{aligned} &设f(n)=\sum_{i=1}^{n-1}gcd(i,n)\\ &那么ans=\sum_{i=1}^{n}f(n)\\ f(n)&=\sum_{d|n}d\times\sum_{i=1}^{n-1}[gcd(i,n)=d]\\ &=\sum_{d|n}d\times\sum_{i=1}^{\frac{n}{d}-1}[gcd(i,\frac{n}{d})=1]\\ &=\sum_{d|n}d\times \phi(\frac{n}{d}) \end{aligned} f(n)f(n)=i=1n1gcd(i,n)ans=i=1nf(n)=dnd×i=1n1[gcd(i,n)=d]=dnd×i=1dn1[gcd(i,dn)=1]=dnd×ϕ(dn)
那么我们就可以在预处理欧拉函数后,用类似埃氏筛的方法,预处理出 f ( n ) ​ f(n)​ f(n),最后对其做一遍前缀和,就得到了最终的答案。

此处给出筛 f ( n ) f(n) f(n)的代码:

for(int i = 1; i*i < MAX; i++){
	ans[i*i] += i*phi[i];
	for(int j = i+1; i*j < MAX; j++){
		ans[i*j] += phi[j]*i+phi[i]*j;
	}
}

由于 d d d n d \frac{n}{d} dn是对称的,我们直接一次累计即可,但对于平方数,只能累计一个答案。

于是你又可以A掉SP3871UVA11424UVA11426.


至此,恭喜你成功用1个套路水掉了七倍经验!!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值