最大公约数

最大公约数

给定整数 N,求 1x,yNGCD(x,y) 为素数的数对 (x,y) 有多少对。

GCD(x,y) 即求 xy 的最大公约数。

输入格式

输入一个整数 N

输出格式

输出一个整数,表示满足条件的数对数量。

数据范围

1N107

输入样例:

4

输出样例:

4

 

解题思路

  直接枚举(x,y)是不可取的,如果定义一种映射关系(x,y)fp,其中p是质数。因此当数对(x,y)的最大公约数为质数就满足这个映射关系。可以发现自变量很多,而因变量很少,因此考虑能不能来枚举因变量来求自变量的个数。

  枚举1N种的每一个质数p,如果有gcd(x,y)=p,那么有gcd(xp,yp)=1。记x=xpy=yp,满足1x,yNp。因此问题从在1N中有多少个(x,y)gcd(x,y)=p变成了在1Np中有多少个(x,y)gcd(x,y)=1,就是可见的点的模型。

  因此对于质数p,所要求的(x,y)的个数为sp=2i=2Npφ(i)+1。因此总的答案就是不超过N的质数psp。因此还需要对φ(i)求一个前缀和。

  AC代码如下:

复制代码
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 typedef long long LL;
 5 
 6 const int N = 1e7 + 10;
 7 
 8 int primes[N], cnt;
 9 bool vis[N];
10 int phi[N];
11 LL s[N];
12 
13 void get_prime(int n) {
14     // phi[1] = 1    // 这题中定义phi(1)=0
15     for (int i = 2; i <= n; i++) {
16         if (!vis[i]) primes[cnt++] = i, phi[i] = i - 1;
17         for (int j = 0; primes[j] <= n / i; j++) {
18             vis[primes[j] * i] = true;
19             if (i % primes[j] == 0) {
20                 phi[primes[j] * i] = phi[i] * primes[j];
21                 break;
22             }
23             phi[primes[j] * i] = phi[i] * (primes[j] - 1);
24         }
25     }
26 }
27 
28 int main() {
29     int n;
30     cin >> n;
31     get_prime(n);
32     for (int i = 1; i <= n; i++) {  // 对phi[i]求前缀和
33         s[i] = s[i - 1] + phi[i];
34     }
35     LL ret = 0;
36     for (int i = 0; i < cnt; i++) {
37         ret += 2 * s[n / primes[i]] + 1;
38     }
39     cout << ret;
40     
41     return 0;
42 }
复制代码

 

参考资料

  AcWing 220. 最大公约数(算法提高课):https://www.acwing.com/video/695/

posted @   onlyblues  阅读(28)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
Web Analytics
点击右上角即可分享
微信分享提示