欧拉项目问题:
如果我们列出
10
下所有3 or 5
的自然数,则得到3, 5, 6 and 9
。这些倍数的总和是23
。找到
3 or 5
下面的1000
的所有倍数之和。
我的C代码:
long int x;
long int y;
long int z = 0;
long int a = 0;
long int b = 0;
for(x= 0; x < 1000; x += 3)
a = a + x;
for(y = 0; y < 1000; y += 5)
b = b + y;
z = a + b;
printf("%lu", z);
return 0;
但是我得到266333
作为输出,这是错误的。我用Python检查了答案,并弄对了。我想知道我在用C代码做错什么。正确的答案是233168
我的Python代码:
print(sum(x for x in range(1000) if x % 3 == 0 or x % 5 == 0))
答案 0 :(得分:8)
某些数字将被3和5整除,您不应将它们相加两次。 这样的代码将给出正确的结果:
long int x,total = 0;
for(x = 0; x < 1000; ++x)
{
if(x % 3 == 0)
total = total + x;
else if(x % 5 == 0)
total = total + x;
}
printf("%ld", total);
在if else if
上方的代码中,请确保数字被3或5整除。并允许在此基础上求和。
可以进一步优化为:
for(x= 0; x < 1000; ++x)
{
if(x%3 == 0 || x%5 == 0)
total = total + x;
}
以上解决方案是O(n),以实现更好的时间复杂度O(1)我们可以使用 Arithmetic Progression,间隔为3到5。
n =给定范围(1 ... R)中给定数字(Num)的倍数总数。在这种情况下(1 ... 1000)
a1 =第一个倍数。在这里是3或5。
an =最后一个倍数。即3Xn
因此,对于给定范围1 ... lastOfRange(不包括lastOfRange),以下代码将计算间隔为3/5(Num)的级数之和。
long SumOfSeries(long Num, long lastOfRange)
{
long multiplesCount = (lastOfRange-1) / Num; //(lastOfRange-1) to exlude the last number 1000 here
long result = multiplesCount * (Num + (multiplesCount * Num)) / 2;//Num = a1, (multiplesCount * Num) = an.
return result;
}
,这可以称为:
long N = 1000;
Sum = SumOfSeries(3, N) + SumOfSeries(5, N) - SumOfSeries(3*5, N);
printf("%ld", total);
答案 1 :(得分:5)
可以通过简单的算术运算来计算答案,而无需进行任何迭代。许多欧拉计画的问题旨在让您思考寻找解决方案的聪明方法,而不仅仅是利用计算机的原始能力来进行计算。
给出正整数 N 和 F ,即 F 的正整数倍数小于 N 是floor(( N -1)/ F )。 (floor( x )是不大于 x 的最大整数。)例如,小于1000的5的倍数是floor(999/5)= floor (199.8)= 199。
让 n 为该底数的倍数((<< em> N -1)/ F )。
第一个倍数是 F ,最后一个倍数是 n • F 。例如,对于1000和5,第一个倍数是5,最后一个倍数是199•5 = 995。
倍数是均匀分布的,因此它们的平均值等于第一个和最后一个的平均值,因此为( F + n F )/ 2。
倍数的总和等于其平均值乘以它们的数量,因此 F 小于 N 的倍数的总和为 n •( F + n • F )/ 2。
正如我们在其他答案和评论中所看到的,将3的倍数之和与5的倍数之和相加会计算3和5的倍数两次。我们可以通过减去这些数字的总和来对此进行更正。 3和5的倍数都是15的倍数。
因此,我们可以使用简单的算法来计算所需的总和,而无需进行任何迭代:
#include <stdio.h>
static long SumOfMultiples(long N, long F)
{
long NumberOfMultiples = (N-1) / F;
long FirstMultiple = F;
long LastMultiple = NumberOfMultiples * F;
return NumberOfMultiples * (FirstMultiple + LastMultiple) / 2;
}
int main(void)
{
long N = 1000;
long Sum = SumOfMultiples(N, 3) + SumOfMultiples(N, 5) - SumOfMultiples(N, 3*5);
printf("%ld\n", Sum);
}
在处理其他Euler项目问题时,您应该寻找类似的想法。
答案 2 :(得分:2)
您正在做的是一些计算错误。您会看到5和3的一些常见倍数,例如15,30,45 ...,因此,由于您将这两个总和相加,因此得到了更高的价值。
稍微修改一下代码就可以解决问题。
for(x= 0; x < 1000; x += 3)
{
if(x%5)
{
a = a + x;
}
}
for(y = 0; y < 1000; y += 5)
b = b + y;
z = a + b;
printf("%lu", z);
答案 3 :(得分:2)
直接翻译您的python代码:
#include <stdio.h>
int main(int argc, char *argv[])
{
int sum = 0;
for (int x = 0; x < 1000; x++)
{
if (x % 5 == 0 || x % 3 == 0)
sum += x;
}
printf("%d", sum);
}
答案 4 :(得分:0)
出于乐趣,我决定给这个问题一些附加的约束。
int sum_multiples(long int m1,long int m2,long int lim)
{
long int sum=0;
for(long int i=m1;i<lim;i=((i+m1)/m1)*m1>((i+m2)/m2)*m2?((i+m2)/m2)*m2:((i+m1)/m1)*m1) sum+=i;
return sum;
}
int main(int argc, char *argv[])
{
printf("Total: %ld \n",sum_multiples(3,5,1000));
return 0;
}
答案 5 :(得分:0)
您的带for循环的解将为O(n)。
我找到了一个更通用的解决方案O(1)。
在这里,我们可以使用另一个乘数,甚至是非素数。
#include <stdio.h>
long gcd(long a, long b) {
return b == 0 ? a : gcd(b, a % b);
}
long lcm(long a, long b) {
return a / gcd(a, b) * b;
}
long sumMultiple(long mult, long to) {
to = to / mult;
to *= to + 1;
return (to >> 1) * mult;
}
long calc(long a, long b, long n) {
n--;
return sumMultiple(a, n) + sumMultiple(b, n) - sumMultiple(lcm(a,b), n);
}
int main() {
int n = 1000;
printf("Sum of multiplies of 3 and 5 is %ld\n", calc(3,5,n));
return 0;
}
答案 6 :(得分:0)
#include<stdio.h>
int main()
{
int sum;
int i;
sum=0;
for(i=0;i<1000;++i)
{
if((i%3==0)||(i%5==0))
{
sum=sum+i;
}
}
printf("%d",sum);
}
输出为233168