我整整工作了一天。 好吧,我的代码现在可以正常工作了;
但是我需要减少执行此代码所需的时间,以及该代码不适用于大的另一个问题 像 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);
}
答案 0 :(得分:2)
代码不适用于大数字,例如long d = 9999999999;
这是由于两个原因:long
的范围不足应为32位,并且long*long
溢出。
要肯定使用9,999,999,999
(34位值)之类的值,请确保使用34+位数学。建议至少使用64位的unsigned long long
。
避免测试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/i
和num%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。