问题描述
一天,小R准备找小h去游泳,当他找到小h时,发现小h正在痛苦地写着一列数,1,2,3,…n,于是就问小h痛苦的原因,小h告诉他,现在他要算1..n这些数里面,1出现的次数是多少,如n=11的时候,有1,10,11共出现4次1,现在给出n,你能快速给出答案么?
输入
一行,就是n,(1<=n<=maxlongint)
输出
一个整数,表示1..n中1出现的次数。
样例输入
11
样例输出
4
算法讨论
我们将数从右往左一位一位拆出来,编号1-n,每一位有三种情况,等于0,等于1,大于1;
1、等于0
当当前位等于0时,当前位1出现的次数仅由更高位决定,即更高位数*当前位权值(i-1)。
2、等于1
当当前位等于1时,当前位1出现的次数不仅由更高位决定,也受更低位限制,即更高位数*当前位权值(i-1)+低位数+1。
3、大于1
当当前位大于1时,当前位1出现的次数仅由更高位决定,即(更高位数+1)*当前位权值(i-1)。
#include <cstdio>
using namespace std;
#define ll long long
int n,l=0;
ll s=0;
int main()
{
scanf("%d",&n);
int x=n,y,p,w=1;
while (x!=0)
{
y=x % 10;
if (y==0)
s+=(x / 10)*w;
if (y==1)
s+=(x / 10)*w+l+1;
if (y>1)
s+=(x / 10+1)*w;
x/=10;
l=l+y*w;
w*=10;
}
printf("%lld",s);
}