1 solutions

  • 2
    @ 2025-5-30 19:49:15

    数位DP的递推模板:

    1. 给足维度,定义状态,用DP预处理;
    2. 先求区间 [0或1, L – 1] 内满足条件的数:把L拆位,然后从高到低依次处理;
    3. 同样的方法处理区间 [0, R]
    4. 利用前缀和思想,solve(R) – solve(L–1) 即为答案。
    #include <bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    
    const int N = 35;
    int a, b;
    // f[i][j]:i位数,以j开头的不降数个数
    int f[N][10];
    
    void init() {
    	for (int i = 0; i <= 9; i++) f[1][i] = 1;
    	for (int i = 2; i < N; i++)
    		for (int j = 0; j <= 9; j++)
    			for (int k = j; k <= 9; k++)
    				f[i][j] += f[i - 1][k];
    }
    
    int num[N];
    LL solve(int x) {
    	if (!x) return 1;
      // 拆位
    	int len = 0;
    	while (x) {
    		num[++len] = x % 10;
    		x /= 10;
    	}
    
      // 记录(从左到右)上一位的数字,因为要保证数字不降
    	int last = 0;
    	LL ans = 0;
    	for (int i = len; i >= 1; i--) {
    		int now = num[i];
    		for (int j = last; j < now; j++)
    			ans += f[i][j];
        // 当前位大于上一位,后续不可能再有不降数了
    		if (last > now) break;
    		last = now;
        // 数位DP需要注意的点:边界值如果符合要求,也要加上!
    		if (i == 1) ans++;
    	}
    	return ans;
    }
    
    int main() {
    	init();
    	while (cin >> a >> b) {
    		//		cout << solve(b) << ' ';
    		//		cout << solve(a - 1) << '\n';
    		cout << (solve(b) - solve(a - 1)) << '\n';
    	}
    
    	return 0;
    }
    
    • 1

    Information

    ID
    166
    Time
    1000ms
    Memory
    512MiB
    Difficulty
    7
    Tags
    # Submissions
    25
    Accepted
    9
    Uploaded By