各位数字之和——一个神奇的结论

今天下午翻了翻XX大学的ACM模版,作为新手,当然挑能看懂的来看,结果就看到了这样一个简单的问题:

题目是这样的,输入一个正整数,将它的各位数字加起来,如果得到的不是一位数,将这个和的各位数字再加起来,如此循环,直到得到一个一位数,最后输出这个个位数。

最简单的方法是使用递归模拟上述求和过程,直到和小于10:

# include <stdio.h>

int dig_sum(int x)
{
int sum = x;
if (x < 10) return sum;
else
{
sum = 0;
while (x > 0)
{
sum += x%10;
x /= 10;
}
return dig_sum(sum);
}
}

int main()
{
int x;

while (~scanf("%d", &x))
printf("%d\n", dig_sum(x));


return 0;
}

递归方法思路很清晰,但是递归往往很耗时,将递归用循环代替,就变成了下面的:

# include <stdio.h>
int main()
{
int x, sum;

while (~scanf("%d", &x))
{
sum = x;
while (sum > 9)
{
sum = 0;
while (x > 0)
{
sum += x%10;
x /= 10;
}
x = sum;
}
printf("%d\n", sum);
}

return 0;
}

但是,问题来了:这样的问题有没有更好的方法,来更快速地得出结果呢?

题目本身给出了两种方法的代码,第一种是上面的递归,第二种则是下面的:

int dig(int x) {return (x+8)%9+1;}

在这段代码的上面还有一句话:【不太明白。。。】
看到这句话和这个只有一句代码的方法,让我开始思考。

一个十进制的正整数可以表示为:

                       也可以写作:

                  而,

                所以

              所以

       如果令

              ,       那么,

              

到这里,就可以发现,如果 x 按照题目要求的最终得到了 数字 c (0<c<10,c 一定不为 0),那么

            

到这里,得到了标题中“神奇的结论”:x 和 c 模 9 同余!而 c 是1~9中的一个数字,所以不难通过 x%9 求得c:

  如果 c<9,那么 c=x%9;

  如果c=9,那么x%9=0。

为了方便,调整一下,写成一句代码,即:c = (x+8)%9+1;

到这里,终于明白了第二种方法是怎么回事了。

当时在上课,瞥见了这道题,本来想用手机搜搜,结果手机欠费了。。。看来以后遇到问题要多锻炼思考。

原文地址:https://www.cnblogs.com/JMDWQ/p/2382359.html