ACM模版

描述

题解

一道动态规划题,考点是数位dp,这里提供两种异曲同工之妙的解法。虽然都是数位dp,但是思路有略微差异。

代码

One:

#include <iostream>
#include <cmath>
#include <cstring>

//#pragma warning(disable:4996)

using namespace std;

typedef long long ll;

ll s;
ll dp[20];  // 前x位中1出现次数(0~9均是如此)

void init()
{
    memset(dp, 0, sizeof(dp));

    int i;
    for (i = 1; i <= 9; i++)
    {
        dp[i] = dp[i - 1] * 10 + pow(10, i - 1);    // 前x-1位出现1次数*10 + 第x位为1的情况数
    }
}

ll count(ll x)
{
    ll result = 0;
    ll len = 0;
    ll digit = 0;
    ll radix = 1;
    ll tail = 0;
    while (x != 0)
    {
        digit = x % 10;
        x = x / 10;

        ++len;

        if (digit > 1)
        {                                           // radix就代表10的多少多少次方
            result += radix + digit * dp[len - 1];  // ex:241 result(200~241) += radix(百位为1)+ digit
        }                                           // * dp[len - 1](0~199除去百位为1)
        else if (digit == 1)
        {                                           // +1是代表取的那个整数
            result += tail + 1 + dp[len - 1];       // ex:141 result(100~141除去百位的1) += tail(101~141百位
        }                                           // 为1) + 1(100的百位为1) + dp[len - 1](0~99)
        tail = tail + digit * radix;                // 头为1个数
        radix *= 10;                                // 倍率
    }
    return result;
}

int main()
{
    //freopen("i.txt","r",stdin);
    //freopen("o.txt","w",stdout);

    init();

    cin >> s;
    cout << count(s)<<endl;

    return 0;
}

Two:

#include <iostream>
#include <cstdio>

using namespace std;

int sum[20];
int getlen(int n)
{
    int num = 0;
    while (n)
    {
        n = n / 10;
        num++;
    }
    return num;
}

int main()
{
    int n, i, t1, t2, len, ans;
    cin >> n;
    len = getlen(n);
    sum[1] = n / 10;
    if (n % 10 >= 1)
    {
        sum[1]++;
    }
    for (i = 2, t1 = 10, t2 = 100; i <= len; i++, t1 = t1 * 10, t2 = t2 * 10)
    {
        if (n / t1 % 10 > 1)
        {
            sum[i] = n / t2 + 1;
            sum[i] = sum[i] * t1;
        }
        else if (n / t1 % 10 == 1)
        {
            sum[i] = n / t2;
            sum[i] = sum[i] * t1 + n % t1 + 1;
        }
        else
        {
            sum[i] = n / t2;
            sum[i] = sum[i] * t1;
        }
    }
    ans = 0;
    for (i = 1; i <= len; i++)
    {
        ans += sum[i];
    }
    cout << ans << endl;
    return 0;
}