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;
}