有效地将数字除以3或5

时间:2018-08-01 17:53:46

标签: c

列出给定数字以下的3或5的倍数之和。

这是我的代码,找不到任何不必要的内容。但是hackerrank表示由于超时而终止,时间限制为2秒才能提供预期的输出。 输入的第一行包含“ t”,它表示测试用例的数量。接下来是每行,每行包含一个整数。

#include <stdio.h>
void calc(int a){
    int sum = 0;
    for(int a0=1; a0<a; a0++){
        if(a0%3==0 || a0%5==0){
            sum+=a0;
        }
    }
    printf("%d", sum);
}
int main(){ 
    int t;
    scanf("%d",&t);
    int arr[t];
    for(int a0 = 0; a0 < t; a0++){
        scanf("%d",&arr[a0]);
    }
    for(int b=0; b<t; b++){
        calc(arr[b]);
           printf("\n");
    }
    return 0;
}

输入

2
10
100

输出必须为

23
2318

如果我们列出所有低于10的自然数,它们是3或5的倍数,则这些倍数的总和为23。

3 个答案:

答案 0 :(得分:5)

选项1

您正在尝试将给定数字下3或5的所有倍数相加。您是否尝试过在没有for循环的情况下如何做?咱们试试吧。嗯,“ 3或5”需要考虑很多。让我们简化一下,并尝试对99下的3的所有倍数求和:

3+6+9+12+15+...+99

如何优化此加法运算以避免for循环? (在继续阅读之前,先这样做)

现在,如果您知道如何在给定n下求和3的所有倍数,那么您是否有办法在给定n下求和3 5的所有倍数?嗯,序列3,6,9,12, 15 ,...,n和5,10, 15 ...,n之间有什么重叠?也许如果您可以将n下的3的倍数相加,并将n下的5的倍数相加,那么您可以摆脱那个overlap吗?

选项2

好的,假设我知道数字n下3或5的倍数之和。这是否有助于我找到数字n + 1下3或5的倍数之和?也许我知道calc(n-1)是什么。如果可以的话,那会很棒,因为我可以只用save calc(n-1)而不是重新计算calc(n-1)。如果只有...

答案 1 :(得分:1)

以下是每个人的一些提示和链接:

  • m = (a - 1) / k下面有a个数字,它们可以被k整除(整数除法)。
  • 他们的总和是m * (m + 1) / 2 * k(由Gaussian sum formula链接到德语Wiki-他们似乎更喜欢Gauß)。
  • 小于a并被35整除的所有数字的总和与

    相同
    + the sum of all numbers smaller than `a` divisible by `3` 
    + the sum of all numbers smaller than `a` divisible by `5` 
    - the sum of all numbers smaller than `a` divisible by `15` 
    

    (通过inclusion-exclusion principle

这为您提供了恒定时间算法:

#include <stdio.h>
/* sums the numbers 
   smaller than `a` that 
   are divisible by `k`
*/
int s(int a, int k) {
    int m = (a - 1) / k;
    return m * (m + 1) / 2 * k;
}

/* sums the numbers smaller than
   a that are divisible by both
   3 and 5
*/
int calc(int a) {
    return s(a, 3) + s(a, 5) - s(a, 15);
}

int main(){ 
    int t;
    scanf("%d", &t);
    int arr[t];
    for(int a0 = 0; a0 < t; a0++){
        scanf("%d", &arr[a0]);
    }
    for(int b=0; b<t; b++){
        printf("input = %d\n", arr[b]);
        printf("%d\n", calc(arr[b]));
    }
    return 0;
}

示例:

$ ./sumFizzBuzz 
4
10
100 
1000
10000
23
2318
233168
23331668

对不起,这一定是,这里和“几乎重复”的问题上有太多循环-和废话……

答案 2 :(得分:-3)

#include <stdio.h>
void calc_faster(int a)
{
    int mid=0,sum=0;
    for(unsigned int i = a-1;i>0;i--)
    {if(i%3==0)
      {
          if(i%5==0)
          {
              mid=i;
              break;
          } else sum+=i;
      } else if(i%5==0) sum+=i;
    }
    sum+=mid*(7*mid+15)/30;
    printf("%d\n",sum);
}
int main()
{
       unsigned int t;
       unsigned int temp;
    scanf("%d",&t);
    unsigned int arr[t];
    for(register unsigned int a0 = 0; a0 < t; a0++)
    {
        scanf("%d",&arr[a0]);
    }
    for(register unsigned int b=0; b<t; b++)
    {
       calc_faster(arr[b]);
    }
    return 0;
}