(C)中分母为d的缩减分数的数量

时间:2018-11-18 03:25:44

标签: c math

我整整工作了一天。 好吧,我的代码现在可以正常工作了;

但是我需要减少执行此代码所需的时间,以及该代码不适用于大的另一个问题 像 long d = 9999999999 ;

所以我希望有人能帮助我解决这个问题 顺便说一下,这就是我正在做的挑战;

https://www.codewars.com/kata/number-of-proper-fractions-with-denominator-d/train/c

我正在尝试使用 Euler的Totient 公式来解决该问题,如ma代码所示; 在这里您可以了解 Euler's Totient 的工作方式。

https://www.dcode.fr/euler-totient

先谢谢。

int is_prime(long num)
{
  long i = 2;
  if (num == 1) return 0;

  for (i; num >= i * i; i++)
      if (num % i == 0) return 0;
  return (1);
}

long properFractions(long d)
{
  long sum = 0;
  long i = 2;
  long double v1 = 1.0; 
  long keep = d;

  for (i; i <= d; i++)
      if(d % i == 0 )
         if (is_prime(i))
             v1 *= (1.0 - (1.0 / i));

  if (keep != 1)
     sum = (keep * v1);
  return (sum);
}

2 个答案:

答案 0 :(得分:2)

  

代码不适用于大数字,例如long d = 9999999999;

这是由于两个原因:long的范围不足应为32位,并且long*long溢出。

  1. 要肯定使用9,999,999,999(34位值)之类的值,请确保使用34+位数学。建议至少使用64位的unsigned long long

  2. 避免测试num >= i * i,因为i*i很容易溢出。使用num/i >= i 1

相反:

int is_prime(unsigned long long num) {
  if (num <= 1) return 0;// Handle 0,1

  unsigned long long i = 2;
  for (i; num/i >= i; i++) {
    if (num % i == 0) {
      return 0;
    }
  }
  return 1;
}

通过首要决定可以实现许多性能改进。但这应该使代码超出“不适用于大数”的要求。


1 好的编译器会看到附近的num/inum%i并经常一起计算它们,而所花费的时间与单独消耗的时间相同。

答案 1 :(得分:1)

您需要找到小于n的互质数。

n = p1^x1 * p2^x2 * ... * pn^xn
phi(n) = p1^(x1-1)*(p1-1) * p2^(x2-1)*(p2-1) * ... * pn^(xn-1)(pn-1) 

现在即使查找较大的数字,也可以得到最多sqrt(n)个数字的质数。完成后,将使用功率计算(在O(logt)的情况下使用a^t)。这样可以获取AC。