51Nod-1009

来源:互联网 发布:linux查看文件系统类型 编辑:程序博客网 时间:2024/05/16 08:44

51Nod-题解


给定一个十进制正整数N,写下从1开始,到N的所有正数,计算出其中出现所有1的个数。
例如:n = 12,包含了5个1。1,10,12共包含3个1,11包含2个1,总共5个1。

思路: 当时第一个想的就是先各位填1,然后补其它位,但当时自己给自己挖了个坑,误以为会有重复数出现,后来发现规律重复数出现并不影响计算1的个数。

例:32145 这个数我们首先把个位填1,就是_ _ _ _ 1,所以其它位可以任意填但必须在3214这个范围内,所以我们的到个位数的第一种情况—— 3214/10 + 1 = 3215 。

同理: 我们把十位数填1,结果就为 _ _ _ 1 _ 。我们先填入高位,有321+1中情况,但个位可以填0-9,所以相乘的话总共就有322*10=3220种情况。

百位填1:_ _ 1 _ _ 这时候有个问题出现了,如果按照上面的方法去填的话,结果为33*100 = 3300,但实际上我们多算了54个数,以为这个1并不是我们去填充的,而是数本身就带的,所以我们填完高位地位并没有0-9这十种情况给我们选择。所以我们需要先退一个数,高位只填到31,之后再统计个位的数。所以结果就是(31+1)* 10 +46 = 3246种。

千位的话则是普通计算规律,得出结果为4000,万位为10000,所以总的结果为 10000 +4000 +3246 +3220 +3215 = 23681

代码如下:

#include <stdio.h>int main(void) {    int n,T,Tn;             // n输入数,T表示判断当前为是否为1或者0,Tn则是用来把n拷贝一份,用于计算当位数为1的情况    int mul = 1;            //标记计算的位,个位十位。。。。。    int result  = 0;        //统计计算的结果    scanf("%d",&n);    Tn = n;    while(n) {        T = n%10 ;        if (T == 1) {                   // 当前位为1时            result += (n/10)*mul;       // 先把高一位减1计算结果            result += (Tn%mul)+1;       // 再计算低位的个数        }  else if(T == 0) {            //当前位为0,不需要+1            result += (n/10)*mul;        }  else {                       // 当前为非0和1,正常计算            result += (n/10+1)*mul;        }        mul *= 10;                      //计算完之后,标记进一位        n /= 10;                        //整个数缩小用于判定    }    printf("%d",result);    return 0;}

运行结果

原创粉丝点击