51nod-1009 数字1的数量(经典好题)

版权声明:随便转哈,说明下出处~ https://blog.csdn.net/qq_40922859/article/details/82024052

1009 数字1的数量 

基准时间限制:1 秒 空间限制:131072 KB 分值: 5 难度:1级算法题

给定一个十进制正整数N,写下从1开始,到N的所有正数,计算出其中出现所有1的个数。

例如:n = 12,包含了5个1。1,10,12共包含3个1,11包含2个1,总共5个1。

Input

输入N(1 <= N <= 10^9)

Output

输出包含1的个数

Input示例

12

Output示例

5

直接暴力肯定会超时,肯定是要求找规律:

对于12,小于等于的数字含有1的个数是5,一位一位来看:个位是1的有1,11:十位是1的有10,11,12,只针对位,所以没有计算重复。

嗯哼~~

对于123,个位,1,11,21, 31,41,51,61,71,81,91,101,111,121      13个,13=(12+1)*1;

                  十位,10~19,110~119                                                       20个, 20=(1+1)*10;

                  百位,100~123                                                                   24个,24=23+1;

往下看~~~

我们现在只观察数字的百位,(其他位也一样)

对于12034;由于百位是0,那么他之后的34就不起作用了,只看前面的“12”就行了,从“1”到“12”,每个后面都有一份“100~199”,就是1100~1199,2100~2199,.......12100~12199,所以说百位含1的就一共有12*100个;

对于12134:一样,和上面的12034差不多,但是百位上是1,那对于百位的低位(十位,个位),34,是不是100~134也都行,所以这时候百位含1的数量就是12*100+35(100~134是35个);

再看看12234:由于百位是2,大于1了,那他的234肯定包含了一个100~199,100个,这时候百位含1的数量就是12*100+100;

即13*100;

为什么百位的就是乘以100?(因为100~199是100个,1000到1999是1000个,以此类推);

所以说,对于每一位,我们需要分三种情况讨论:

(以下用cnt代替这一位含1的数量,前面的部分用left代替,后面部分的用right代替)

如12345计算百位时,left=12,right=45;

1:假如这一位是0,那么这一位的含1的数量

cnt=left x 这一位的数量级;

2:   假如这一位大于1,

cnt=(left+1) x  这一位的数量级;

3:   假如这一位是1;

cnt=left x 数量级 +right+1;

看懂了吧。

还不懂?推荐港巨博客:点这里

代码:

#include<iostream>
using namespace std;
int Cal(int n){
	int cnt=0;
	int i=1;        //数量级,逐渐增大到最高位 
	int cur=0,left=0,right=0;
	while(n/i){
		
		cur=(n/i)%10;    //cur,当前位的数字 
		left=n/(i*10);
		right=n%i;
		
		if(cur>1){
			cnt+=(left+1)*i;
		}
		else if(cur==0){
			cnt+=left*i;
		}
		else if(cur==1){
			cnt+=left*i+right+1;
		}
		i*=10; 
	}
	return cnt; 
}
int main(){
	int n;
	while(cin>>n){
		cout<<Cal(n)<<endl;
	}
	return 0;
} 

猜你喜欢

转载自blog.csdn.net/qq_40922859/article/details/82024052