×

第七篇:P1390

原题题面

Alex_wei's数论与筛法Part1

显然,这道题有两种方法(本来有三种,但其实第三种和第二种相同)。
显然:

\(\sum_{i=1}^n \sum_{j=i+1}^n (i,j) = \frac{\sum_{i=1}^n \sum_{j=1}^n (i,j)- \sum_{i=1}^n i}{2}\)

\(\sum_{i=1} ^n i = \frac{n\times(n+1)}{2}\)

\(\begin{aligned} \sum_{i=1}^n \sum_{j=1}^n (i,j) &= \sum_d d \sum_{i=1}^n \sum_{j=1}^n [(i,j) = d] \\ &= \sum_d d \sum_{i=1}^{\frac{n}{d}} \sum_{j=1}^{\frac{n}{d}} [(i,j) = 1] \end{aligned}\)

第一种

令 \(S_n = \sum_{i=1}^n \varphi_n\)
显然,\(\sum_{i=1}^n \sum_{j=1}^n [(i,j) = 1] = 2\times S_n - \varphi_1 = 2\times S_n - 1\)
所以原式等于 \(\sum_{d=1}^n d\times (2\times S_\frac{n}{d} - 1)\),\(O(n)\) 解决即可。
代码:

#include<bits/stdc++.h>
using namespace std;
#define N 2000005
#define intl long long
#define For(i,a,b) for(intl i=a;i<=b;i++)
#define deo(i,a,b) for(intl i=a;i>=b;i--)
intl read() {
	intl x=0,k=1;char ch=getchar();
	while(!isdigit(ch)) {if(ch == '-') k=-1;ch=getchar();}
	while(isdigit(ch)) {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
	return x*k;
}
intl vis[N], phi[N], mu[N],sum[N];
vector<intl> prim;
void init() {
	phi[1] = mu[1] = 1;
	For(i,2,N-5) {
		if(!vis[i]) prim.push_back(i), mu[i] = -1, phi[i] = i-1;
		for(auto x:prim) {
			if(i*x > N-5) break;
			vis[i*x] = 1;
			if(i%x == 0) {phi[i*x] = phi[i]*x;break;}
			mu[i*x] = mu[i]*mu[x], phi[i*x] = phi[i]*phi[x];
		}
	}
	For(i,1,N-5) sum[i] = sum[i-1]+phi[i];
}
int main() {
	init();
	intl n = read(), ans = 0;
	For(i,1,n) ans += i*(2*sum[n/i] - 1);
	printf("%lld\n", (ans - n*(n+1)/2)/2);
	return 0;
}


第二种

由 $[n = 1] = \sum_{d|n} \mu_d $

\(\begin{aligned} \sum_d d \sum_{i=1}^{\frac{n}{d}} \sum_{j=1}^{\frac{n}{d}} [(i,j) = 1] &= \sum_d d \sum_{i=1}^{\frac{n}{d}} \sum_{j=1}^{\frac{n}{d}} \sum_{t|(i,j)} \mu_t \\ &= \sum_d d \sum_t \mu_t \sum_{i=1}^\frac{n}{d} [t|i] \sum_{j=1} ^\frac{n}{d} [t|j] \\ &= \sum_d d \sum_t \mu_t \frac{n}{dt} \frac{n}{dt} \\ &= \sum_T \lfloor \frac{n}{T} \rfloor \lfloor \frac{n}{T} \rfloor \sum_{d|T} d \mu_{ \frac{T}{d}} \\ &= \sum_T \lfloor \frac{n}{T} \rfloor \lfloor \frac{n}{T} \rfloor \varphi_T \end{aligned}\)

\(O(n)\) 解决。

代码:

#include<bits/stdc++.h>
using namespace std;
#define N 2000005
#define intl long long
#define For(i,a,b) for(intl i=a;i<=b;i++)
#define deo(i,a,b) for(intl i=a;i>=b;i--)
intl read() {
	intl x=0,k=1;char ch=getchar();
	while(!isdigit(ch)) {if(ch == '-') k=-1;ch=getchar();}
	while(isdigit(ch)) {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
	return x*k;
}
intl vis[N], phi[N], mu[N],sum[N];
vector<intl> prim;
void init() {
	phi[1] = mu[1] = 1;
	For(i,2,N-5) {
		if(!vis[i]) prim.push_back(i), mu[i] = -1, phi[i] = i-1;
		for(auto x:prim) {
			if(i*x > N-5) break;
			vis[i*x] = 1;
			if(i%x == 0) {phi[i*x] = phi[i]*x;break;}
			mu[i*x] = mu[i]*mu[x], phi[i*x] = phi[i]*phi[x];
		}
	}
}
int main() {
	init();
	intl n = read(), ans = 0;
	For(i,1,n) ans += (n/i)*(n/i)*phi[i];
	printf("%lld\n", (ans - n*(n+1)/2)/2);
	return 0;
}


posted @ 2026-10-05 17:25  shiori123  阅读(4)  评论(0)    收藏  举报