PAT-A-1049 Counting Ones (30 分) 数位DP C++题解

博客介绍了PAT-A-1049 Counting Ones问题,通过数位动态规划(DP)方法解决。文章详细阐述了题目要求,即计算1到n数字中1的总数,并提供了递归枚举与记忆化存储的解题思路。作者分享了AC代码,强调使用64位整数避免溢出,以及利用记忆化存储加速递归过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1049 Counting Ones (30 分)

题目传送门:1049 Counting Ones (30 分)

一看到这道题就知道考的是数位DP,倔强的我不想找模板~~,自己写才有成就感。昨晚临睡觉前开始写的,今天早起继续写,居然一交就AC了,呵呵,开心????

一、题目大意

给定一个正整数n,求1到n的数字中,所有数含1的数量。
Sample:
12
5
赠送样例:
123
57

二、解题思路

递归枚举每一位+记忆化存储

例如n=123,将n存到vector<int>v中,v={1, 2, 3}, 从高位开始枚举,最高位下标pos=0,小于等于n的数字中,最高位的值i可以取0、1,也就是可以取[0, v[pos]],而当i==v[pos],它的下一位pos只能取[0, v[pos+1]], i!=v[pos]的话,下一位pos可以取[0, 9]。两者上限的不同是由于当前位的值i是否等于v[pos]引起的,当i==v[pos]时,当前位已经达到了这个位的上限,使下一位pos+1位最多取到n中pos+1位的值,也就是下一位最多可以取[0, v[pos+1]], 如果超过v[pos+1],则数会超过n,不符合要求。当i!=v[pos]时,说明当前位的值并没有达到该位的上限,下一位则可以任意取[0, 9]中的数字。

注意点:

  1. 使用64位整数,32位会爆。
  2. 使用记忆化存储,加快递归搜索的速度。定义一个三维数组:dp[pos][val][limit],存储当前位为pos, 值为val, limit表示当前位是否受限。当遍历到pos, val, limit的时候,先看dp数组中是否已经存在该值,如果不存在则进行dfs递归搜索遍历,遍历完计算出结果后,存入到dp中记下来,供下一次使用。如果存在dp值,则直接返回该dp值。
  3. 如果当前位的值为1,则需要累加这位为1时多产生的1的数量,如果不受限,则加pow(10, v.size() - pos - 1),如果受限则加当前位后面所有数字构成的整数。

三、AC代码

#include<bits/stdc++.h>
using namespace std;
using ll = unsigned long long;
int n;
vector<int>v;
void init(){
   
	while(n){
   
		v.push_back
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值