洛谷P1390 公約數的和題解

第一道莫比烏斯反演題
要求的式子是 ∑ i = 1 n ∑ j = i + 1 n g c d ( i , j ) , n < = 2 ∗ 1 e 6 \sum_{i=1}^{n}\sum_{j=i+1}^{n}gcd(i,j),n<=2*1e6 i=1nj=i+1ngcd(i,j),n<=21e6,一組數據
可以轉換成 ∑ i = 1 n ∑ j = 1 n g c d ( i , j ) − ∑ i = 1 n g c d ( i , i ) 2 \frac{\sum_{i=1}^{n}\sum_{j=1}^{n}gcd(i,j)-\sum_{i=1}^{n}gcd(i,i)}{2} 2i=1nj=1ngcd(i,j)i=1ngcd(i,i)
只要解決 ∑ i = 1 n ∑ j = 1 n g c d ( i , j ) \sum_{i=1}^{n}\sum_{j=1}^{n}gcd(i,j) i=1nj=1ngcd(i,j)即可
常規套路(?)枚舉gcd
式子變成 ∑ p = 1 n p ∑ i = 1 n ∑ j = 1 n ( g c d ( i , j ) = p ) \sum_{p=1}^{n}p\sum_{i=1}^{n}\sum_{j=1}^{n}(gcd(i,j)=p) p=1npi=1nj=1n(gcd(i,j)=p)
g c d ( i , j ) = p gcd(i,j)=p gcd(i,j)=p,必有 g c d ( i / p , j / p ) = 1 gcd(i/p,j/p)=1 gcd(i/p,j/p)=1
枚舉範圍可以除以 p p p,再轉換成 ∑ p = 1 n p ∑ i = 1 n / p ∑ j = 1 n / p ( g c d ( i , j ) = 1 ) \sum_{p=1}^{n}p\sum_{i=1}^{n/p}\sum_{j=1}^{n/p}(gcd(i,j)=1) p=1npi=1n/pj=1n/p(gcd(i,j)=1)
( g c d ( i , j ) = 1 ) (gcd(i,j)=1) (gcd(i,j)=1)可以轉換成 ∑ d ∣ g c d ( i , j ) μ ( d ) \sum_{d|gcd(i,j)}\mu(d) dgcd(i,j)μ(d)
式子變成 ∑ p = 1 n p ∑ i = 1 n / p ∑ j = 1 n / p ∑ d ∣ g c d ( i , j ) μ ( d ) \sum_{p=1}^{n}p\sum_{i=1}^{n/p}\sum_{j=1}^{n/p}\sum_{d|gcd(i,j)}\mu(d) p=1npi=1n/pj=1n/pdgcd(i,j)μ(d)
嗯嗯式子怎麼越來越複雜了
開始提出 μ \mu μ,枚舉 d d d,式子變成 ∑ p = 1 n p ∑ d = 1 n μ ( d ) ⌊ n / p d ⌋ 2 \sum_{p=1}^{n}p\sum_{d=1}^{n}\mu(d){\lfloor n/pd \rfloor}^2 p=1npd=1nμ(d)n/pd2
怎麼突然變成這樣?
因爲 d ∣ g c d ( i , j ) d|gcd(i,j) dgcd(i,j),有 d ∣ i d|i di, d ∣ j d|j dj
μ ( d ) \mu(d) μ(d)被加上的次數是 1 − n / p 1-n/p 1n/p d d d的倍數個數(合法的 i i i)乘上 1 − n / p 1-n/p 1n/p中的 d d d的倍數個數(合法的 j j j),就是乘法原理
μ ( d ) \mu(d) μ(d)被加上的次數不就是 ⌊ n / p d ⌋ 2 {\lfloor n/pd \rfloor}^2 n/pd2
但是現在好像已經可以過了???
枚舉 p p p O ( n ) O(n) O(n)的,枚舉 d d d l o g log log的, ⌊ n / p d ⌋ 2 > 0 {\lfloor n/pd \rfloor}^2>0 n/pd2>0時式子纔有值,實際上會更小。
n / 1 + n / 2 + n / 3 + . . + n / n ≈ n l o g n n/1+n/2+n/3+..+n/n\approx n log n n/1+n/2+n/3+..+n/nnlogn,就是 N O I P 2020 T 2 NOIP2020T2 NOIP2020T2的那個“調和級數”
2 ∗ 1 e 6 ∗ l o g ( 2 ∗ 1 e 6 ) < = 50000000 2*1e6*log(2*1e6)<=50000000 21e6log(21e6)<=50000000,沒有一點問題。
但是我們可以做到 O ( n ) O(n) O(n)
T = p d T=pd T=pd
我們再化化式子,變成了 ∑ T = 1 n ∑ p = 1 n p μ ( T / p ) ⌊ n / T ⌋ 2 \sum_{T=1}^{n}\sum_{p=1}^{n}p\mu(T/p){\lfloor n/T \rfloor}^2 T=1np=1npμ(T/p)n/T2
解釋一下:首先p可以放進去,這個就是乘法分配律。
根據乘法分配律, ⌊ n / T ⌋ 2 {\lfloor n/T \rfloor}^2 n/T2可以提出來
式子變成 ∑ T = 1 n ⌊ n / T ⌋ 2 ∑ p = 1 n p μ ( T / p ) \sum_{T=1}^{n}{\lfloor n/T \rfloor}^2\sum_{p=1}^{n}p\mu(T/p) T=1nn/T2p=1npμ(T/p)
然後 ∑ p = 1 n p μ ( T / p ) \sum_{p=1}^{n}p\mu(T/p) p=1npμ(T/p)就是 φ ( T ) \varphi(T) φ(T)
如果想看證明戳這
式子變成 ∑ T = 1 n ⌊ n / T ⌋ 2 φ ( T ) \sum_{T=1}^{n}{\lfloor n/T \rfloor}^2\varphi(T) T=1nn/T2φ(T)
線性篩 φ ( T ) \varphi(T) φ(T),可以達到 O ( n ) O(n) O(n)
事實上 ⌊ n / T ⌋ 2 {\lfloor n/T \rfloor}^2 n/T2也可以整除分塊達到log級別,以用來對付多種數據





























#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 2000005
#define ll long long
using namespace std;
ll i,j,k,m,n,o,p,l,s,t;
ll pr[N],phi[N],bz[N];
int main()
{
   
   
	freopen("gcdsum.in","r",stdin);
	freopen("gcdsum.out","w",stdout);
	scanf("%lld",&n);
	phi[1]=1;
	for (i=2;i<=N-5;i++)
	{
   
   
		if (!bz[i]) pr[++pr[0]]=i,bz[i]=1,phi[i]=i-1;
		for (j=1;j<=pr[0]&&i*pr[j]<=N-5;j++)
		{
   
   
			bz[i*pr[j]]=1;
			if (i%pr[j]) phi[i*pr[j]]=phi[i]*(pr[j]-1);
			else phi[i*pr[j]]=pr[j]*phi[i];
			if (!(i%pr[j])) break;
		}
	}
	for (i=1;i<=n;i++) s+=(n/i)*(n/i)*phi[i];
	s-=n*(n+1)/2; 
	printf("%lld\n",s>>1ll);
	return 0; 
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章