2023-04-10:给定两个正整数x、y,都是int整型(java里)
返回0 ~ x以内,每位数字加起来是y的数字个数。
比如,x = 20、y = 5,返回2,
因为0 ~ x以内,每位数字加起来是5的数字有:5、14,
x、y范围是java里正整数的范围,
x <= 2 * 10^9,
y <= 90。
输入:1000,4。
输出:15。
输入:2000,6。
输出:49。
来自CISCO。

答案2023-04-10:

本文介绍了两种解决给定 x 和 y,求 0~x 中每位数字之和为 y 的数字个数的方法。第一种方法使用暴力枚举的方式,遍历 0~x 中的每一个数字,计算其每位数字之和是否等于 y,并统计符合条件的数字数量。第二种方法使用动态规划的思想,通过数位 DP 的方式快速计算符合条件的数字数量。

  1. 暴力枚举法

暴力枚举法是一种朴素的解题思路,对于每个数字,我们可以循环计算其每位数字之和,然后判断是否等于 y,如果是,则计数器加 1。这种方法看似简单,但由于需要遍历 x 个数,时间复杂度为 O(x * log(x)),不能满足本题要求的时间复杂度。

  1. 数位 DP

数位 DP 是一种常见的动态规划思想,主要用于解决与数字相关的问题。其基本思路是将数字按照位数拆分,然后根据各位数字的限制条件(如数字大小、数字和等)进行状态转移,最终得到答案。

本题中,我们可以使用数位 DP 来计算符合条件的数字数量。具体来说,假设当前处理到数字 x 的第 i 位,已经确定前 i-1 位的数字为 num,则当前的状态可以表示为 (i, num, sum),其中 sum 表示前 i 位数字之和。根据此状态定义,我们可以设计转移方程如下:

如果 i == 0,则返回 sum 是否等于 y 的结果,即 count(x, i, num, sum) = if sum == y {1} else {0}。

否则,设当前处理到的数字为 cur,则有两种情况:

当 cur <= sum 时,对答案的贡献为 get_form(i-1, sum-cur),即在第 i-1 位上选择符合条件的数字,然后将其放在当前位置上。

当 cur == x / offset % 10 时,需要递归计算下一位数字的方案总数,即 count(x, i-1, num+cur*offset, sum-cur)。

最终的答案为 count(x, len, 0, y),其中 len 表示数字 x 的位数,offset 表示当前处理到的位数所代表的权值。

为了提高效率,我们可以使用记忆化搜索来避免重复计算。具体来说,我们可以使用一个二维数组 dp 来记录已经计算过的状态,如果当前状态已经被计算过,则直接返回其对应的结果。

同时,由于在转移方程中需要频繁地查询 get_form(i, sum) 函数,这会导致函数调用次数过多,降低程序效率。因此,我们可以在程序运行前先预处理出所有可能的状态下的方案数,然后使用静态数组保存结果,在程序运行时直接查询即可。

综上所述,本题的数位 DP 解法时间复杂度为 O(log(x) * y),空间复杂度为 O(log(x) * y)。相比于暴力枚举法,数位 DP 基于动态规划的思想,通过状态转移方程快速计算答案,具有更高的效率和更好的可拓展性。

rust代码如下:

fn num1(x: i32, y: i32) -> i32 {
let mut ans = 0;
for i in 0..=x {
if check1(i, y) {
ans += 1;
}
}
ans
} fn check1(num: i32, y: i32) -> bool {
let mut sum = 0;
let mut n = num;
while n != 0 {
sum += n % 10;
n /= 10;
}
sum == y
} fn num2(x: i32, y: i32) -> i32 {
if x < 0 || y > 90 {
return 0;
}
if x == 0 {
return if y == 0 { 1 } else { 0 };
}
let mut offset = 1;
let mut len = 1;
while offset <= x / 10 {
offset *= 10;
len += 1;
}
let mut dp = vec![vec![-1; (y + 1) as usize]; (len + 1) as usize];
count(x, offset, len, y, &mut dp)
} fn count(x: i32, offset: i32, len: i32, rest: i32, dp: &mut Vec<Vec<i32>>) -> i32 {
if len == 0 {
return if rest == 0 { 1 } else { 0 };
}
if dp[len as usize][rest as usize] != -1 {
return dp[len as usize][rest as usize];
}
let mut ans = 0;
let cur = (x / offset) % 10;
for i in 0..cur.min(rest + 1) {
ans += get_form((len - 1) as usize, (rest - i) as usize);
}
if cur <= rest {
ans += count(x, offset / 10, len - 1, rest - cur, dp);
}
dp[len as usize][rest as usize] = ans;
ans
} // 打表
const FORM_SIZE: usize = 11;
const FORM_SUM: usize = 91; static mut FORM: [[i32; FORM_SUM]; FORM_SIZE] = [[0; FORM_SUM]; FORM_SIZE]; fn init_form() {
unsafe {
FORM[0][0] = 1;
for len in 1..=10 {
for sum in 0..=len * 9 {
for cur in 0..=9.min(sum as i32) {
FORM[len as usize][sum as usize] +=
FORM[(len - 1) as usize][(sum - cur) as usize];
}
}
}
}
} fn get_form(len: usize, sum: usize) -> i32 {
unsafe { FORM[len][sum] }
} fn main() {
println!("{}", i32::MAX);
init_form();
println!("{}", num1(88739128, 37));
println!("{}", num2(88739128, 37)); println!("{}", num1(1000, 4));
println!("{}", num2(1000, 4)); println!("{}", num1(2000, 6));
println!("{}", num2(2000, 6));
}

2023-04-10:给定两个正整数x、y,都是int整型(java里) 返回0 ~ x以内,每位数字加起来是y的数字个数。 比如,x = 20、y = 5,返回2, 因为0 ~ x以内,每位数字加起的更多相关文章

  1. C/C++代码优化之求两个整型的平均值

    在 C/C++ 中, 直接利用 (x + y) >> 1 来计算 \(\left\lfloor {\left( {x + y} \right)/2} \right\rfloor\) (两个 ...

  2. 给定表达式[x/2] + y + x * y, 其中x,y都是正整数。

    改进了一下,不过还是要十多秒吧. package com.boco.study; import java.math.BigDecimal; import java.util.Calendar; imp ...

  3. caffe+Ubuntu14.04.10 +cuda7.0/7.5+CuDNNv4 安装

    特别说明: Caffe 官网地址:http://caffe.berkeleyvision.org/ 本文为作者亲自实验完成,但仅限用于学术交流使用,使用本指南造成的任何不良后果由使用者自行承担,与本文 ...

  4. LeetCode 周赛 342(2023/04/23)容斥原理、计数排序、滑动窗口、子数组 GCB

    本文已收录到 AndroidFamily,技术和职场问题,请关注公众号 [彭旭锐] 提问. 大家好,我是小彭. 前天刚举办 2023 年力扣杯个人 SOLO 赛,昨天周赛就出了一场 Easy - Ea ...

  5. 2019-6-27-WPF-如何给定两个点画出一条波浪线

    title author date CreateTime categories WPF 如何给定两个点画出一条波浪线 lindexi 2019-6-27 10:17:6 +0800 2019-6-26 ...

  6. 给定两个数组,这两个数组是排序好的,让你求这两个数组合到一起之后第K大的数。

    题目:给定两个数组,这两个数组是排序好的,让你求这两个数组合到一起之后第K大的数. 解题思路: 首先取得数组a的中位数a[aMid],然后在b中二分查找a[aMid],得到b[bMid],b[bSt] ...

  7. 输入两个正整数m和n,求其最大公约数和最小公倍数

    public static void main(String[] args){  Scanner sc = new Scanner (System.in);  int a,b;  System.out ...

  8. Ubuntu LTS 系统学习使用体会和实用工具软件汇总 6.04 8.04 10.04 12.04 14.04 16.04

    Ubuntu LTS 系统学习体会和工具软件汇总 6.04 8.04 10.04 12.04 14.04 16.04 ubuntu入门必备pdf:http://download.csdn.net/de ...

  9. 给定两个字符串 s 和 t,它们只包含小写字母。 字符串 t 由字符串 s 随机重排,然后在随机位置添加一个字母。 请找出在 t 中被添加的字母。

    给定两个字符串 s 和 t,它们只包含小写字母.字符串 t 由字符串 s 随机重排,然后在随机位置添加一个字母.请找出在 t 中被添加的字母. 示例: 输入: s = "abcd" ...

  10. 给定两个有序整数数组 nums1 和 nums2,将 nums2 合并到 nums1 中,使得 num1 成为一个有序数组

    题目描述: 给定两个有序整数数组 nums1 和 nums2,将 nums2 合并到 nums1 中,使得 num1 成为一个有序数组. 说明:初始化 nums1 和 nums2 的元素数量分别为 m ...

随机推荐

  1. PyQt5高级窗口组件

    https://blog.csdn.net/A642960662/article/details/123093350?utm_medium=distribute.pc_aggpage_search_r ...

  2. 修改百分浏览器(centbrowser)、谷歌和火狐浏览器默认字体的方法

    1,百分浏览器(centbrowser) 在浏览器的安装位置D:\Program Files\Cent Browser\User Data编辑文件custome.css,如果没有此文件可新建一个,内容 ...

  3. STM32上特殊管脚应用 重映射那个GPIO_Remap_SWJ_JTAGDisable

    对于初学习者来说为什么用到PB3和PB4时无法控制输出呢? 下面就这一问题进行分析讲解. 首先,STM32F10x系列的MCU复位后,PA13/14/15 & PB3/4默认配置为JTAG功能 ...

  4. Javaweb学习笔记第六弹

    本章节的存在意义是:学到PreparedStatement反应较慢,理解不透彻,来做个比较,加深印象 详细讲述PrepareStatement 与 Statement 连接数据库的部分区别 在我学习的 ...

  5. 深入了解 JavaScript 内存泄漏

    作者:京东零售 谢天 在任何语言开发的过程中,对于内存的管理都非常重要,JavaScript 也不例外. 然而在前端浏览器中,用户一般不会在一个页面停留很久,即使有一点内存泄漏,重新加载页面内存也会跟 ...

  6. 页面div垂直内容超出后,edge浏览器右侧没有自动出现滚动条

    搜索网上解决办法,是给父元素添加样式 overflow-y:scroll; height:100vh; 但此举只是给该父元素侧边添加滚动条,而且不好配合回到顶部这一效果 最后发现是在父组件的包裹元素中 ...

  7. 机器学习基础05DAY

    分类算法之k-近邻 k-近邻算法采用测量不同特征值之间的距离来进行分类 优点:精度高.对异常值不敏感.无数据输入假定 缺点:计算复杂度高.空间复杂度高 使用数据范围:数值型和标称型 一个例子弄懂k-近 ...

  8. MYSQL 最左匹配原则的原理

    https://blog.csdn.net/Andrew_Chenwq/article/details/125242197最左匹配原则最左匹配原则就是指在联合索引中,如果你的 SQL 语句中用到了联合 ...

  9. ACM-NEFU15届校赛-大二组

    A.小林找工作 #include<bits/stdc++.h> using namespace std; const int MAXN=1e5+10; int p[MAXN]; int m ...

  10. MySQL explain 和 profiling 详解

    MySQL explain 和 profiling 详解 mysql explain MySQL 的 EXPLAIN 是一个用于查询优化的工具,它可以显示 MySQL 数据库如何执行查询.它返回一组关 ...