Miraclys

一言(ヒトコト)

Luogu P2568 GCD

\(\large{题目链接}\)
\(\\\)
求:

\[\sum\limits_{p \in prime}\sum[\gcd(x,y)=p],1 \leqslant \ x,y \ \leqslant n \leqslant 10^{7} \]

\(\\\)
当复习一下今天学习的欧拉函数,考虑式子:

\[\sum\limits_{p \in prime}\ \sum\limits_{i=1}^{n} \ \sum\limits_{j=1}^{n} [\gcd(i,j)=p] \\ \sum\limits_{p \in prime}\sum\limits_{i=1}^{\lfloor\tfrac{n}{p}\rfloor}\sum\limits_{j=1}^{\lfloor\tfrac{n}{p}\rfloor} [\gcd(i,j)=1] \\ \sum\limits_{p \in prime} \left( \sum\limits_{i=1}^{\lfloor\tfrac{n}{p}\rfloor} \left(\sum\limits_{j=1}^{i} [\gcd(i,j)=1] \times 2 \right)- \sum_{k=1}^{\lfloor\tfrac{n}{p}\rfloor}[\gcd(k,k)=1]\right) \]

因为\(\sum_{k=1}^{i}[\gcd(k,k)]=1\)中只有\([\gcd(1,1)=1]=1\),其余都为0,对结果没有影响,所以我们可以把式子写为:

\[\sum_{p \in prime} \left( \sum\limits_{i=1}^{\lfloor\tfrac{n}{p}\rfloor} \varphi(i) \times 2 - 1\right) \]

\(\\\)
然后我们可以求出\(\varphi(i)\)后求出\(\varphi(i)\)的前缀和,方便枚举\(prime\)时直接查询。

#include <bits/stdc++.h>
using namespace std;

const int N = 1e7 + 5;
typedef long long ll;
ll n, cnt, vis[N], pri[N], phi[N], sum[N];

ll read() {
	ll x = 0, f = 1;
	char c = getchar();
	while (!isdigit(c)) {
		if (c == '-') f = -1;
		c = getchar();
	}
	while (isdigit(c)) x = x * 10 + c - '0', c = getchar();
	return x * f;
}

inline void varphi() {
	phi[1] = 1;
	for (int i = 2; i <= n; ++i) {
		if (!vis[i]) {
			vis[i] = i;
			phi[i] = i - 1;
			pri[++cnt] = i;
		}
		for (int j = 1; j <= cnt && pri[j] * i <= n; ++j) {
			vis[i * pri[j]] = pri[j];
			if (i % pri[j] != 0) phi[pri[j] * i] = (pri[j] - 1) * phi[i];
			else {
				phi[i * pri[j]] = phi[i] * pri[j];
				break;
			}
		}
	}
} 

int main() {
	n = read();
	varphi();
	ll ans = 0;
	//for (int i = 1; i <= n; ++i) cout << phi[i] << " ";
	//cout << endl; 
	//ans = cnt;
	//phi[1] = 0;
	for (int i = 1; i <= n; ++i) sum[i] = sum[i - 1] + phi[i];
	for (int i = 1; i <= cnt; ++i) {
		ans += (sum[n / pri[i]] << 1) - 1;
	}
	printf("%lld\n", ans);
	return 0;
}
posted @ 2022-09-17 23:07  Miraclys  阅读(15)  评论(0编辑  收藏  举报

关于本博客样式

部分创意和图片借鉴了

BNDong

的博客,在此感谢