51nod 1009 数字1的数量

来源:互联网 发布:美橙域名查询 编辑:程序博客网 时间:2024/05/17 06:25
给定一个十进制正整数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,这里重点解释一下这句话:

 

    if(!limit && dp[pos]!=-1)return num*Pow(pos+1)+dp[pos];

为什么这里ruturn的是num*Pow(pos+1)+dp[pos]。dp[pos]代表当数字有pos位的时候有多少个1,但是这里统计是不完全的,假设这是一个k位数字,(因为是数位dp,所以dp[pos]实际上存的是从个位到pos位的1的数量,那么pos位之后的那些1怎么算呢?在这里直接可以用num记录下来当到pos位之后(我们假设百位后面是千位万位十万位等等)有多少个1,那么这时pos位一共包含了多少个数字,再乘以num就是pos位后面的1的数量了,再加上dp[pos],就是应该return的值了)


代码

#include<iostream>#include<cstdio>#include<cstring>using namespace std;const int maxn = 10;int dp[maxn], a[maxn];int Pow(int k){    int num=1;    for(int i = 1; i <=k;i++)num*=10;    return num;}int dfs(int pos, int num, int limit){    if(pos == -1) return num;    if(!limit && dp[pos] != -1) return num*Pow(pos+1)+dp[pos];    int up = limit ? a[pos] : 9;    int tmp = 0;    for(int i = 0; i <= up; i++)        tmp += dfs(pos-1, num+(i==1), limit && a[pos] == i);    if(!limit) dp[pos] = tmp;    return tmp;}int solve(int x){    int pos = 0;    while(x)    {        a[pos++] = x%10;        x /= 10;    }    return dfs(pos-1, 0, 1);}int main(){    int n;    memset(dp, -1, sizeof(dp));    while(cin >> n)        printf("%d\n", solve(n));    return 0;}


1 0
原创粉丝点击