【问题标题】:Can you solve my problem and simplify my code? I could not find out with the clean solution for this specific problem你能解决我的问题并简化我的代码吗?我无法找到针对此特定问题的干净解决方案
【发布时间】:2020-08-22 21:24:30
【问题描述】:

问题:要显示此模式的 n 项的总和,例如 1+11+111+1111+11111..n 项

测试数据:

输入词条数:5。

预期输出:

1 + 11 + 111 + 1111 + 11111 总和是:12345

我正在尝试这种方式->

//To display the sum of series like 1+11+111+11111

 #include <stdio.h>
 int
 main(void){
//Here i declared some variables for storing information
 int number,iteration,value=1,j,summation=0;


 //Message to user
 printf("Input the number of terms : ");
 //taking input from the user
 scanf("%d",&number);
 //this condition will work till the iteration reaches to the inputted number

 for(iteration=1; iteration<=number; iteration++){

    
    for(j=1; j<=iteration; j++){
            //To display the series like 1 11 111 1111 11111
            printf("%d",value);


        if(j==1){
        summation=summation+value;

        }
        else if(j==2){
        summation=summation+value*10;
        }
        else if(j==3){
        summation=summation+value*100;
        }
        else if(j==4){
        summation=summation+value*1000;
        }
        else if(j==5){
        summation=summation+value*10000;
        }




}


printf(" ");
}
printf("\n");
//To display the summation
printf("The summation is : %d",summation);
return 0;}

现在我的问题是:这段代码不符合我的预期。它正在输入值 5。但是当我想输入 6 次时,我需要在我的代码中另外添加一个 else if 条件。每当我增加输入值时,我都需要执行此任务。

当输入值为 6 并且我需要添加并制作这样的条件时->

else if(j==6){
       summation=summation+value*100000;
             }

所以我认为,这不是正确解决问题的方法。每次我需要对输入的值做同样的事情。我怎么解决这个问题?。之后如何简化解决方案?我相信你们比我更专业。请与我分享你的知识。提前谢谢你。

【问题讨论】:

  • 对于 n 个术语 @Yunnosch
  • 也许尝试递归?注意整数类型的有限范围...unsigned long long 至少为 64 位,能够容纳高达 18446744073709551615 的值
  • 将 2000 万个数字加起来,最多 2000 万位数,您需要使用的不仅仅是一个整数变量
  • @Bob__ 该字符串需要容纳约 4000 万个字符。这就是我所说的“不仅仅是一个变量”;)
  • @Ashifulislamprince 你有你正在解决的原始问题的链接吗?

标签: c


【解决方案1】:

将输入的数字传递给这个函数。

    int findSum(int n) 
    { 
        int sum=0, cnt= 1; 
        for (int i = 1; i <= n; i++) { 
            sum += cnt; 
            cnt = (cnt * 10) + 1; 
        } 
      
        return sum; 
    } 

【讨论】:

  • @Yunnosch 我同意!然后 int 可以替换为 long long int 之类的东西。我想这样就可以了。
  • 谢谢先生。我会以这种方式尝试@Atharva Kango
【解决方案2】:

如果你想让这个函数适用于大 N(比如 1,000 或 20,000,000),你将无法使用 intlong long 值。相反,您可以分配一个uint8s 数组,并执行您自己的逐位加法运算,包括进位运算。然后在最后打印结果。它不会很快,但它会起作用。

为了让您的代码保持简单,请从右到左思考。从第零个数组元素中的最低有效位开始。

【讨论】:

    【解决方案3】:

    这是一个使用uint64_t 表示更大数字的示例。它显示了您想要的 1 到 20 位的输出(更长会导致溢出)。

    诀窍是通过乘以 10 再加 1,从前一个数字生成数字 1、11、111 等。例如,11111 = 1111 * 10 + 1。

    #include <inttypes.h>
    #include <stdio.h>
    
    void sum(int n) {
        uint64_t t = 0;
        uint64_t x = 1;
        for (int i = 0; i < n; i++) {
            if (i > 0) printf(" + ");
            printf("%" PRIu64, x);
            t += x;
            x = (x * 10) + 1;
        }
        printf(" = %" PRIu64 "\n", t);
    }
    
    int main() {
        for (int i = 1; i < 21; i++) {
            sum(i);
        }
    }
    

    这是适用于任何n 的版本。它以 n 为单位线性计算总时间,尽管打印要求和的项必然需要 O(n^2) 时间。

    代码的工作原理是,总数的最后一位由添加的 n 个 1s 和倒数第二个 n-1 1s 组成,依此类推。当然还有随身携带。请注意,结果总是正好是 n 位。

    #include <stdio.h>
    #include <stdlib.h>
    
    void sum(int n) {
        for (int i = 1; i <= n; i++) {
            if (i > 1) printf(" + ");
            for(int j = 0; j < i; j++) putchar('1');
        }
        printf(" = ");
    
        char *s = malloc(n + 1);
        s[n] = '\0';
        int t = 0;
        for (int i = n - 1; i >= 0; i--) {
            t += i + 1;
            s[i] = '0' + (t % 10);
            t /= 10;
        }
        printf("%s\n", s);
        free(s);
    }
    
    int main() {
        sum(50);
    }
    

    输出(包装):

    1 + 11 + 111 + 1111 + 11111 + 111111 + 1111111 + 11111111 + 111111111 + 1111111111 + 11111111111 + 111111111111 +
    1111111111111 + 11111111111111 + 111111111111111 + 1111111111111111 + 11111111111111111 + 1111111111111111 11 +
    1111111111111111111 + 11111111111111111111 + 111111111111111111111 + 1111111111111111111111 + 11111111111111111111111 +
    111111111111111111111111 + 1111111111111111111111111 + 11111111111111111111111111 + 11111111111 1111111111111111 +
    1111111111111111111111111111 + 11111111111111111111111111111 + 111111111111111111111111111111 +
    1111111111111111111111111111111 + 11111111111111111111111111111111 + 111111111111111111111111111111111 +
    1111111111111111111111111111111111 + 11111111111111111111111111111111111 + 111111111111111111111111111111111111 +
    1111111111111111111111111111111111111 + 11111111111111111111111111111111111111 + 1111111111111111111111111
    11111111111111 + 1111111111111111111111111111111111111111 + 11111111111111111111111111111111111111111 +
    111111111111111111111111111111111111111111 + 1111111111111111111111111111111111111111111 + 1111111111111111111111111
    1111111111111111111 + 111111111111111111111111111111111111111111111 + 1111111111111111111111111111111111111111111111 +
    11111111111111111111111111111111111111111111111 + 111111111111111111111111111111111111111111111111 +
    1111111111111111111111111111111111111111111111111 + 11111111111111111111111111111111111111111111111111 =
    12345679012345679012345679012345679012345679012340
    

    【讨论】:

    • 答案中的每个代码都会失败。也许 Ashful 应该使用 big int(char*)
    • @Yunnosch 包含一个适用于所有 n 的版本 :)
    【解决方案4】:

    为了处理大于 int/long 限制的数字,您可以使用数组来获取每个数字的总和并将输出打印为字符串。

    #include <stdio.h>
    
    int
    main (int argc, char *argv[])
    {
        int n, i, j;
        
        scanf("%d", &n);
        
        char ones[n];
        char sum[n + 1]; // + 1 index in case of a carry out
        char output[n + 2]; // +1 more index than sum for null byte
        
        // initialize to 0s
        for (i = 0; i < n; i++) {
            ones[i] = sum[i] = output[i] = 0;
        }
        sum[n] = output[n] = output[n+1] = 0;
        
        for (i = 0; i < n; i++) {
            ones[i] = 1;
            output[i] = '1';
            for (j = 0; j <= i; j++) { // add the current number of ones to sum
                sum[j] += ones[j];
                if (sum[j] >= 10) { // if theres a carry
                    sum[j + 1] += (sum[j] / 10); // add the carry to the next index
                    sum[j] %= 10; // keep the last digit
                }
            }
            
            if (i == n - 1) {
                printf ("%s ", output);
            } else printf ("%s + ", output);
        }
        
        if(sum[n] == 0) {// leading digit is 0
            i = n - 1;
        } else i = n;
        
        for (j = 0; i >= 0; i--, j++) {
            output[j] = sum[i] + '0';
        }
        printf ("The sum is: %s\n", output);
        
        return 0;
    }
    

    【讨论】:

      【解决方案5】:

      给定用户输入变量number,代码可能如下所示:

      //...
      
      if (number < 0)
      {
          // do some error handling
          return -1;
      }
      
      int value_to_add = 1;
      int sum = 0;
      
      while (number--)
      {
          sum += value_to_add;
          value_to_add = value_to_add * 10 + 1;
      }
      
      // ... (result is in "sum")
      

      您也可以考虑溢出的可能性(当结果变得如此之大以至于它不适合 int 时)。例如,您可以限制用户输入 (number)。

      【讨论】:

      • 谢谢先生@Manuel H
      【解决方案6】:

      很高兴为您提供帮助!

      (好像是功课,希望你能学到点东西)

      您正在使用许多“如果”来决定它应该加多少。另一种方法是每次都使用*10+1

      请看代码:

      #include <stdio.h>
      long long sum,tmp=1,n;
      int main(void){
          scanf("%lld",&n);
          for(int i=0;i<n;i++){
              if(i<n-1)printf("%lld + ",tmp);
              else printf("%lld ",tmp);
              sum+=tmp;
              tmp=tmp*10+1;
          }
          printf("= %lld",sum);
          return 0;
      }
      

      就是这样。

      祝你有美好的一天:)

      【讨论】:

      • 赞到 1000 @Yunnosch
      【解决方案7】:

      如果我理解正确,您希望能够以编程方式添加新术语,而无需使用 if 语句。我建议你这样做

      for (j=0; j<=iteration; j++){
         int powerOf10 = (int) pow((double) 10,j); //power elevation: notice 10^0=1, 10^1=10..    
         summation+=value*powerOf10;
      }
      

      这只是为了给你一个想法。显然,这段代码可以进一步细化。 如果你不明白我为计算 powerOf10 执行的所有转换,我给你留下这个帖子:Why is my power operator (^) not working?

      【讨论】:

      • 已确认。 @Yunnosch
      • 对不起,我不敢相信。不能将 1000 位数字存储到 int 中。
      • 好的,我该怎么处理1000位数字?
      • 是的,显然您必须始终考虑您正在使用的数字的大小。我再给你一些你现在可能想要的整数类型的参考(来自 stdint.h):stackoverflow.com/questions/6013245/…
      【解决方案8】:

      Paul Hankin 的answer 展示了如何解决n 的值大于long long 中可存储的位数的问题。

      根据一个简单的观察,这种方法可以与另一种方法结合使用。如果我们从最大的数开始写总和,我们可以注意到一个新出现的模式。

       111111111111111111111111111111111111111111111...111 +
        11111111111111111111111111111111111111111111...111 +
                                     ... 
               1111111111111111111111111111111111111...111 =
       ----------------------------------------------------
       123456789999999999999999999999999999999999999...999 +   
                111111111111111111111111111111111111...111 =
       ----------------------------------------------------
       123456790111111111111111111111111111111111111...110 +
                 11111111111111111111111111111111111...111 +
                                     ...
                        1111111111111111111111111111...111 =
       ----------------------------------------------------
       123456790123456789999999999999999999999999999...998 +
                         111111111111111111111111111...111 =
       ----------------------------------------------------
       123456790123456790111111111111111111111111111...109 +
                          11111111111111111111111111...111 +
                                     ...
                                 1111111111111111111...111 =
       ----------------------------------------------------
       123456790123456790123456789999999999999999999...997 +
                                  111111111111111111...111 =
       ----------------------------------------------------
       123456790123456790123456790111111111111111111...108 +
       ^        ^        ^        ^  ...
      

      在实践中,我们可以从从左到右使用重复模式"123456790"(最高有效数字始终为'1')“填充”数字(表示为n 字符的字符串)。

      然后,从最低有效位开始,我们可以应用带进位求和的算法,但只要计算出的数字与已经存在的数字不同(最后一位除外,它总是n % 10 )。

      只需要几个步骤,就在n的十进制位数附近。

      【讨论】:

        猜你喜欢
        • 2016-05-21
        • 2020-12-28
        • 2021-09-06
        • 2020-09-03
        • 2023-04-03
        • 1970-01-01
        • 1970-01-01
        • 2011-01-24
        • 2021-08-14
        相关资源
        最近更新 更多