AcWing 338. 计数问题(数位dp)

这个题的意思是分别求 0 - 9 在 1 - n中出现的个数,是个数位动态规划的内容,难度还是比较大的。

题目

特殊情况:

  1. x在第1位上出现的次数(不用考虑前半段):
    bcdefg∈[00000,bcdefg] , ans += bcdefg+1
  2. x在最后一位上出现的次数(不用考虑后半段):

如果g<x,那么不存在这样的数,ans += 0
如果g==x,那么有一个这样的数,ans += 1
如果g>x,yyyyyy∈[000000,abcdef] , ans += abcdef+1
3) 如果我们枚举的数是0的话 :

0不能在第一位
而且枚举到的这一位前面不能全是0,即
xxx∈[001,abc-1]

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.ArrayList;

class Main {
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static PrintWriter pw = new PrintWriter(System.out);

    public static void main(String[] args) throws IOException {
        String[] s;
        while (true) {
            s = br.readLine().split(" ");
            int a = Integer.parseInt(s[0]);
            int b = Integer.parseInt(s[1]);
            if (a == 0 && 0 == b) break;
            if (a > b) {
                int temp = a;
                a = b;
                b = temp;
            }
            for (int i = 0; i <= 9; i++) pw.print(count(b, i) - count(a - 1, i) + " ");
            pw.println();
        }
        pw.flush();
        pw.close();
        br.close();
    }

    public static int count(int n, int x) {
        if (n == 0) return 0;
        ArrayList<Integer> nums = new ArrayList<>();
        while (n != 0) {
            nums.add(n % 10);
            n /= 10;
        }
        n = nums.size();
        int res = 0;
        int bit = x == 0 ? 1 : 0;
        for (int i = n - 1 - bit; i >= 0; i--) {
            if (i < n - 1) {
                res += get(nums, n - 1, i + 1) * Math.pow(10, i);
                if (x == 0) res -= Math.pow(10, i);
            }
            if (nums.get(i) > x) res += Math.pow(10, i);
            else if (nums.get(i) == x) res += get(nums, i - 1, 0) + 1;
        }
        return res;
    }

    public static int get(ArrayList<Integer> al, int l, int r) {
        int res = 0;
        for (int i = l; i >= r; i--) res = res * 10 + al.get(i);
        return res;
    }


}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值