AcWing 220 最大公约数
题目
给定整数 ,求 且 为素数的 有多少对
分析
用朴素的算法求解显然复杂度为 ,所以考虑变形:
观察后两个和式,可以发现下面这个与它形式相近的式子能转化为欧拉函数的形式:
将上式乘 ,可以发现它与最开始的式子相比,多加了 且 的部分,此时 ,设集合 表示小于等于 的素数,那么多加的次数就等于 ,所以原式可以化为:
其中 表示欧拉函数的 项前缀和
那么我们可以用线性筛以 同时筛出素数和欧拉函数,并以 计算前缀和,所以时间复杂度为
代码
#include<bits/stdc++.h>
using namespace std;
const int MAX_N = 10000000 + 5;
int n, cnt = 0;
bool is_prime[MAX_N];
int prime[MAX_N], phi[MAX_N];
long long sum[MAX_N];
void sieve(int n)
{
memset(is_prime, 1, sizeof(is_prime));
cnt = 0;
is_prime[1] = false;
phi[1] = 1;
for(int i = 2; i <= n; i++) {
if(is_prime[i]) {
prime[++cnt] = i;
phi[i] = i - 1;
}
for(int j = 1; j <= cnt && prime[j] * i <= n; j++) {
int t = prime[j] * i;
is_prime[t] = false;
if(i % prime[j]) {
phi[t] = phi[i] * phi[prime[j]];
} else {
phi[t] = phi[i] * prime[j];
break;
}
}
}
}
int main()
{
cin >> n;
sieve(n);
long long ans = 0;
sum[0] = 0;
for(int i = 1; i <= n; i++)
sum[i] = sum[i - 1] + phi[i];
for(int i = 1; i <= cnt; i++)
ans += 2ll * sum[n / prime[i]];
ans -= cnt;
cout << ans << endl;
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】