数位dp,HDU 5179 beautiful number

一、题目

1、题目描述

Let A=∑ni=1ai∗10n−i(1≤ai≤9)(n is the number of A's digits). We call A as “beautiful number” if and only if a[i]≥a[i+1] when 1≤i Could you tell me the number of “beautiful number” in the interval [L,R](including L and R)?

2、输入输出

2.1输入

The fist line contains a single integer T(about 100), indicating the number of cases.
Each test case begins with two integers L,R(1≤L≤R≤109).

2 1 11 999999993 999999999

2.2输出

For each case, output an integer means the number of “beautiful number”.


10 2

3、原题链接

Problem - 5179 (hdu.edu.cn)


二、解题报告

1、思路分析

美丽数要求数位从高位到低位非升序,然后要求高位跟任意一位比它低的位取余为0

数位dp处理非升序很容易,那么怎么处理第二个条件呢?

我们根据基础数论的知识b ≡ 0 (mod c) ,a ≡ 0 (mod b),则a ≡ 0 (mod c),发现我们只要让前一位的因数作为下一位即可

所以我们用0~9的数字作为状态即可

2、复杂度

时间复杂度:O(nlogn) 空间复杂度:O(nlogn)

3、代码详解

#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
const int N = 10;
int f[N][N], d[N];

int dfs(int n, int pre, bool lim, bool zero)
{
    if (!n)
        return 1;
    if (lim && !zero && ~f[n][pre])
        return f[n][pre];
    int res = 0, ceil = lim ? 9 : d[n];
    for (int i = 0; i <= ceil; i++)
        if (zero)
            res += dfs(n - 1, i, lim || i < ceil, !i);
        else if (i && i <= pre && pre % i == 0)
            res += dfs(n - 1, i, lim || i < ceil, 0);

    if (lim && !zero)
        return f[n][pre] = res;
    return res;
}

void solve()
{
    int a, b, i = 0;
    cin >> a >> b;
    a--;
    while (b)
        d[++i] = b % 10, b /= 10;
    int r = dfs(i, 0, false, true);
    i = 0;
    while (a)
        d[++i] = a % 10, a /= 10;
    int l = dfs(i, 0, false, true);
    cout << r - l << '\n';
}

int main()
{
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    // freopen("in.txt", "r", stdin);
    int _ = 1;
    cin >> _, memset(f, -1, sizeof(f));
    while (_--)
        solve();
    return 0;
}

你可能感兴趣的:(OJ刷题解题报告,算法,c++,动态规划,数据结构)