51nod 1009 数字1的数量(数位dp)

来源:互联网 发布:武器知乎 编辑:程序博客网 时间:2024/06/06 09:22

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


题解:数位入门题啊,直接更像数学题。


我们用dp[x]表示从1~(10^x)-1中1的个数。对于每一个数N我们从最后一位开始往前扫,对于每一位digit,我们已经有了digit之后的数XXX中1的个数,那么我们需要的求出来的就是digitXXX包含的1的个数。我们分两种情况digit大于1或者digit等于1,digit等于0对于当前求出来的所有的1没有任何影响,具体求法见代码。


代码如下:


#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>using namespace std;#define LL long longLL dp[20];void init(){memset(dp,0,sizeof(dp));for(int i=1;i<=12;++i)dp[i]=dp[i-1]*10+pow(10,i-1);//预处理每位数中1的个数,例如i=3,就是1~999中含有1的个数 }LL solve(LL cnt){LL ans=0,len=0,digit;LL tali=0,radix=1;while(cnt){digit=cnt%10;cnt/=10;len++;if(digit>1)ans += radix + digit*dp[len-1];//radix表示10^(len-1),例如len=3,就会有100~199这些数要计算,前导的1会产生radix个 else if(digit==1)ans += tali+1+dp[len-1];//tali表示dight后面的数,例如cnt=1395,dight=3,所以tali=95 tali+=digit*radix;radix*=10;}return ans;}int main(){LL n;init();while(scanf("%lld",&n)!=EOF){LL ans=solve(n);printf("%lld\n",ans);}return 0;} 



0 0
原创粉丝点击