鱼C论坛

 找回密码
 立即注册
查看: 2900|回复: 5

题目72:分母不超过一百万的最简真分数的集合中包含多少元素?

[复制链接]
发表于 2015-11-5 16:25:21 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
Counting fractions

Consider the fraction, n/d, where n and d are positive integers. If n<d and HCF(n,d)=1, it is called a reduced proper fraction.

If we list the set of reduced proper fractions for d ≤ 8 in ascending order of size, we get:

1/8, 1/7, 1/6, 1/5, 1/4, 2/7, 1/3, 3/8, 2/5, 3/7, 1/2, 4/7, 3/5, 5/8, 2/3, 5/7, 3/4, 4/5, 5/6, 6/7, 7/8

It can be seen that there are 21 elements in this set.

How many elements would be contained in the set of reduced proper fractions for d ≤ 1,000,000?

题目:

考虑分数 n/d, 其中 n 和 d 是正整数。如果 n<d 并且最大公约数 HCF(n,d)=1, 它被称作一个最简真分数。

如果我们将 d ≤ 8 的最简真分数按照大小的升序列出来,我们得到:

1/8, 1/7, 1/6, 1/5, 1/4, 2/7, 1/3, 3/8, 2/5 , 3/7, 1/2, 4/7, 3/5, 5/8, 2/3, 5/7, 3/4, 4/5, 5/6, 6/7, 7/8

可知该集合中共有 21 个元素。

d ≤ 1,000,000 的最简真分数集合中包含多少个元素?
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2016-10-16 13:49:59 | 显示全部楼层
本帖最后由 jerryxjr1220 于 2017-10-12 10:55 编辑

这题其实也是欧拉函数的扩展。
欧拉函数phi(n)定义了小于n的正整数与n互质的个数。
那么sum(phi(2~8))=21
同样,本题就是求解sum(phi(2~1000000))

  1. from time import clock
  2. start = clock()

  3. def getPrime(n):
  4.     primes = [True]*n
  5.     primes[0], primes[1] = False, False
  6.     for (i, prime) in enumerate(primes):
  7.         if prime:
  8.             for j in range(i*i,n,i):
  9.                 primes[j] = False
  10.     primelist = []
  11.     for (k, trueprime) in enumerate(primes):
  12.         if trueprime:
  13.             primelist.append(k)
  14.     return primelist

  15. def philist(n):
  16.     primelist = getPrime(n)
  17.     PHI = [0]*(n+1)
  18.     for eachprime in primelist:
  19.         PHI[eachprime] = eachprime - 1
  20.     for i in range(len(primelist)):
  21.         p = primelist[i]
  22.         for k in range(p*p,n+1,p):
  23.                 PHI[k] = PHI[int(k/p)]*(p-1)
  24.         for j in range(p*p,n+1,p*p):
  25.             PHI[j] = PHI[int(j/p)]*p
  26.     return PHI
  27. plist = philist(1000000)

  28. print(sum(plist))

  29. end = clock()
  30. print ('Time:%.3f sec' % (end-start))
复制代码

303963552391
Time: 4.211 sec
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-6-26 19:44:57 | 显示全部楼层
jerryxjr1220 发表于 2016-10-16 13:49
这题其实也是欧拉函数的扩展。
欧拉函数phi(n)定义了小于n的正整数与n互质的个数。
那么sum(phi(2~8 ...

厉害!!
但是过程有瑕疵:
  1. def philist(n):
  2.     primelist = getPrime(n)
  3.     # 上面获取质数时要变成getPrime(n+1)
复制代码

检验:
r(11) == r(10) + 10
而你的却是
r(11) == r(10)
因为在边界处恰好为质数, 你没有获取到, 造成phi[11] = 0
上面的BUG只有在边界为质数时显示.
另外, 共享个比较高效的获取质数的方法:
  1. def get_primes( n ):
  2.     t = list(range(3,n,2))
  3.     for i in range(len(t)):
  4.         if t[i]:
  5.             t[i+t[i]::t[i]] = [0] * len( t[i+t[i]::t[i]] )
  6.     return [2] + [x for x in t if x]
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-12-19 11:11:09 | 显示全部楼层
  1. P = []
  2. L = list(range(1000001))
  3. for i in range(2, len(L)):
  4.   if L[i] == i:
  5.     P.append(i)
  6.     L[i] = i - 1
  7.   for p in P:
  8.     if i * p >= len(L):
  9.       break
  10.     if i % p == 0:
  11.       L[i*p] = L[i] * p
  12.       break
  13.     L[i*p] = L[i] * (p - 1)

  14. L[1] = 0
  15. print(sum(L))
复制代码

基于线性筛的方法
https://github.com/devinizz/project_euler/blob/master/page02/72.py
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-9-3 10:25:37 | 显示全部楼层
303963552391

Process returned 0 (0x0)   execution time : 0.064 s
Press any key to continue.
线性筛打表,欧拉函数递推(来自2#69题的方法)
  1. #include<iostream>
  2. #include<cmath>
  3. using namespace std;

  4. const int M = 1e6;
  5. int ct = 0;
  6. bool prime[M+10];
  7. int factor[M+10];
  8. int phi[M+10] = {0};

  9. void euler_sieve(){
  10.   prime[1] = false;
  11.   for (int i = 2;i <= M;i++) prime[i] = true;

  12.   for (int i = 2;i <= M;i++){
  13.     if (prime[i]) {factor[++ct] = i;  phi[i] = i-1;}
  14.     for (int j = 1;j <= ct && i*factor[j] < M;j++){
  15.       prime[i*factor[j]] = false;
  16.       if (i % factor[j] == 0) break;
  17.     }
  18.   }
  19. }

  20. void ini(){
  21.   for (int i = 2;i <= sqrt(M);i++){
  22.     if (prime[i]){
  23.       for (int j = i;j*i <= M;j++)
  24.         if (j % i == 0) phi[j*i] = phi[j] * i;
  25.         else            phi[j*i] = phi[j] * (i-1);
  26.     }
  27.   }
  28. }

  29. int main(){
  30.   unsigned long long ans = 0;
  31.   euler_sieve();  ini();

  32.   for (int d = 2;d <= M;d++)
  33.     //cout << phi[d] << endl;
  34.     ans += phi[d];

  35.   cout << ans << endl;
  36.   return 0;
  37. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

发表于 2021-6-23 23:33:14 | 显示全部楼层
C++ 20ms
  1. #include<iostream>
  2. #include<vector>
  3. #include<cstring>



  4. int main() {
  5.     using namespace std;
  6.     ios::sync_with_stdio(false);

  7.     constexpr unsigned int UPPER_BOUND = 1000000;
  8.     static bool is_prime[UPPER_BOUND];
  9.     static unsigned int phi[UPPER_BOUND];
  10.     vector<unsigned int> primes;
  11.     unsigned int i, k;
  12.     unsigned long long result = 0;

  13.     memset(is_prime, -1, UPPER_BOUND);
  14.     is_prime[0] = is_prime[1] = 0;


  15.     for (i = 2; i < UPPER_BOUND; i++) {
  16.         if (is_prime[i]) {
  17.             primes.push_back(i);
  18.             result += phi[i] = i - 1;
  19.         }

  20.         for (unsigned int j : primes) {
  21.             k = i * j;

  22.             if (k >= UPPER_BOUND) {
  23.                 break;
  24.             }

  25.             is_prime[k] = false;

  26.             if (!(i % j)) {
  27.                 result += phi[k] = phi[i] * j;
  28.                 break;
  29.             }

  30.             result += phi[k] = phi[i] * (j - 1);
  31.         }
  32.     }


  33.     cout << result << endl;
  34.     return 0;
  35. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-5-11 15:13

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表