数位DP

来源:互联网 发布:淘宝虚拟商品有哪些 编辑:程序博客网 时间:2024/06/05 09:24

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[i]表示 1~10^(i-1) 内数字1 的个数

for(int i=1;i<15;++i){      dp[i]=dp[i-1]*10+po;      po*=10;}
然后对于每一位数字,要考虑数字与1的关系。
好比141,到第三个1的时候,实际上已经算出了1~41的1的数量,那我把这个数量想象成是在100~141里面除开开头的1的数量,加上42个开头的1,这个还没算。然后还有的就是1~99的1的数量。
    if(digit>1) ans+=digit*dp[i-1]+po;    else if(digit==1) ans+=dp[i-1]+tail+1;
这里的ans要不断累加,表示每一位上1的数字。

code:
#include <iostream>#include <stdio.h>#include <string.h>#define LL long longusing namespace std;LL dp[15];void init(){    memset(dp,0,sizeof(dp));    LL po=1;    for(int i=1; i<15; ++i)    {        dp[i]=dp[i-1]*10+po;        po*=10;    }}int main(){    LL x;    init();    while(scanf("%lld",&x)!=EOF)    {        LL po=1,tail=0,ans=0;        int digit,i=1;        while(x)        {            digit=x%10;            x/=10;            if(digit>1) ans+=digit*dp[i-1]+po;            else if(digit==1) ans+=dp[i-1]+tail+1;            ++i;            tail+=digit*po;            po*=10;        }        printf("%lld\n",ans);    }    return 0;}