数位DP - 数字1的数量

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 
#include 
#include 
#define LL long long

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










你可能感兴趣的:(动态规划)