SGU[102] Coprimes
Description
描述
For given integer N (1<=N<=10^4) find amount of positive numbers not greater than N that coprime with N. Let us call two positive integers (say, A and B, for example) coprime if (and only if) their greatest common divisor is 1. (i.e. A and B are coprime iff gcd(A,B) = 1).
对于给定的整数N(1<=N<=10^4)求不大于N并且与N互素的正整数的个数。我们称两个正整数(例如A、B)互素,但且仅当它们的最大公约数为1。(即gcd(A,B)=1)
Input
输入
Input file contains integer N.
输入文件包含整数N。
Output
输出
Write answer in output file.
将答案输出在输出文件上。
Sample Input
样例输入
9
Sample Output
样例输出
6
Analysis
分析
我首先想到的是欧拉函数φ(N),后来发现数据量并不是特别的大,所以又用暴力做了一遍,也AC了。
这道题目的重点在于欧拉函数φ(N)的求法,现总结如下:
欧拉函数φ(N):小于等于N且与N互素的正整数的个数。
欧拉函数据有如下性质:
-
φ(1)=1
-
φ(N)=N⋅∏p|N(p−1p),其中p为素数
-
φ(pk)=pk−pk−1=(p−1)⋅pk−1,其中p为素数
-
φ(mn)=φ(m)⋅φ(n),其中gcd(m,n)=1
根据第2个式子我们就可以求出欧拉函数。
基本思路:首先置φ(N)=N,然后枚举N的素因子p,将p的整数倍的欧拉函数φ(k⋅p)置φ(k⋅p)=φ(k⋅p)⋅(p−1p)即可。
基本代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | #include <iostream> using namespace std; const int MAX = 1024; int N; int p[MAX], phi[MAX]; int main() { cin >> N; for ( int i = 1; i <= N; i++) // 初始化 { p[i] = 1; phi[i] = i; } p[1] = 0; // 1不是素数 for ( int i = 2; i <= N; i++) // 筛素数 { if (p[i]) { for ( int j = i * i; j <= N; j += i) { p[j] = 0; } } } for ( int i = 2; i <= N; i++) // 求欧拉函数 { if (p[i]) { for ( int j = i; j <= N; j += i) // 处理素因子p[i] { phi[j] = phi[j] / i * (i - 1); // 先除后乘,防止中间过程超出范围 } } } cout << "Primes: " << endl; for ( int i = 1; i <= N; i++) { if (p[i]) { cout << i << " " ; } } cout << endl; cout << "Euler Phi Function: " << endl; for ( int i = 1; i <= N; i++) { cout << phi[i] << " " ; } return 0; } |
Solution
解决方案
欧拉函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | #include <iostream> #include <math.h> #include <stdio.h> using namespace std; int phi( int x); int main() { int N; cin >> N; cout << phi(N) << endl; cout << endl; return 0; } int phi( int x) { int nRet = x; int nTmp = ( int ) sqrt (x); for ( int i = 2; i <= nTmp; i++) { if (x % i == 0) { nRet = nRet / i * (i - 1); while (x % i == 0) { x /= i; } } } if (x > 1) { nRet = nRet / x * (x - 1); } return nRet; } |
暴力:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | #include <iostream> #include <math.h> #include <stdio.h> using namespace std; int gcd( int x, int y); int main() { int N, nRet = 0; cin >> N; for ( int i = 1; i <= N; i++) { if (gcd(N, i) == 1) { nRet++; } } cout << nRet << endl; return 0; } int gcd( int x, int y) { if (y == 0) { return x; } return gcd(y, x % y); } |
SGU不愧是经典题目的合集,每做一道题都会学到一些新的东西。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步