洛谷P2602 [ZJOI2010]数字计数 题解 数位DP
题目链接:https://www.luogu.com.cn/problem/P2602
题目大意:
计算区间 \([L,R]\) 范围内 \(0 \sim 9\) 各出现了多少次?
解题思路:
使用 数位DP 进行求解。
定义一个结构体数组 \(f[pos][all0]\) 表示满足如下条件时 \(0 \sim 9\) 出现的次数:
- 当前所在数位为第 \(pos\) 位;
- \(all0\) 为 \(1\) 表示当前状态之前一直都是前置 \(0\) ,为 \(0\) 表示前面的数位上面出现过不为 \(0\) 的数。
然后定义一个返回值为此结构体类型的函数 dfs(int pos, int all0, bool limit)
进行求解,其中:
- \(pos\) 和 \(all0\) 的含义同上;
- \(limit\) 表示是否处于限制状态。
实现代码如下:
// P2602 [ZJOI2010]数字计数
#include <bits/stdc++.h>
using namespace std;
long long cnt[10], pow10[22], num;
int a[22];
struct Node {
long long arr[10];
Node() { memset(arr, 0, sizeof(arr)); }
void merge(Node v) {
for (int i = 0; i < 10; i ++)
arr[i] += v.arr[i];
}
} f[22][2];
bool vis[22][2];
void init() {
pow10[0] = 1;
for (int i = 1; i <= 18; i ++) pow10[i] = pow10[i-1] * 10;
}
Node dfs(int pos, int all0, bool limit) {
if (pos < 0) return Node();
if (!limit && vis[pos][all0]) return f[pos][all0];
int up = limit ? a[pos] : 9;
Node tmp = Node();
for (int i = 0; i <= up; i ++) {
if (i == 0 && all0 && pos>0) ;
else {
if (limit && i==up) tmp.arr[i] += num % pow10[pos] + 1;
else tmp.arr[i] += pow10[pos];
}
tmp.merge(dfs(pos-1, all0&&i==0, limit&&i==up));
}
if (!limit) {
vis[pos][all0] = true;
f[pos][all0] = tmp;
}
return tmp;
}
Node get_num(bool minus1) {
long long x;
cin >> x;
if (minus1) x --;
num = x;
int pos = 0;
while (x) {
a[pos++] = x % 10;
x /= 10;
}
if (num == 0) a[pos++] = 0;
return dfs(pos-1, true, true);
}
int main() {
init();
Node res_l = get_num(true);
Node res_r = get_num(false);
for (int i = 0; i < 10; i ++) {
if (i) putchar(' ');
cout << res_r.arr[i] - res_l.arr[i];
}
cout << endl;
return 0;
}
洛谷P2602 [ZJOI2010]数字计数 题解 数位DP的更多相关文章
- 洛谷P2602 [ZJOI2010] 数字计数 (数位DP)
白嫖的一道省选题...... 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 usin ...
- 洛谷P2602 [ZJOI2010]数字计数 题解
题目描述 输入格式 输出格式 输入输出样例 输入样例 1 99 输出样例 9 20 20 20 20 20 20 20 20 20 说明/提示 数据规模与约定 分析 很裸的一道数位DP的板子 定义f[ ...
- 洛谷P2602 [ZJOI2010]数字计数(数位dp)
数字计数 题目传送门 解题思路 用\(dp[i][j][k]\)来表示长度为\(i\)且以\(j\)为开头的数里\(k\)出现的次数. 则转移方程式为:\(dp[i][j][k] += \sum_{t ...
- 洛谷 P2602 [ZJOI2010]数字计数
洛谷 第一次找规律A了一道紫题,写篇博客纪念一下. 这题很明显是数位dp,但是身为蒟蒻我不会呀,于是就像分块打表水过去. 数据范围是\(10^{12}\),我就\(10^6\)一百万一百万的打表. 于 ...
- [洛谷P2602][ZJOI2010]数字计数
题目大意:求区间$[l,r]$中数字$0\sim9$出现个数 题解:数位$DP$ 卡点:无 C++ Code: #include <cstdio> #include <iostrea ...
- 洛谷P2606 [ZJOI2010]排列计数(数位dp)
题目描述 称一个1,2,...,N的排列P1,P2...,Pn是Magic的,当且仅当2<=i<=N时,Pi>Pi/2. 计算1,2,...N的排列中有多少是Magic的,答案可能很 ...
- 【洛谷】2602: [ZJOI2010]数字计数【数位DP】
P2602 [ZJOI2010]数字计数 题目描述 给定两个正整数a和b,求在[a,b]中的所有整数中,每个数码(digit)各出现了多少次. 输入输出格式 输入格式: 输入文件中仅包含一行两个整数a ...
- BZOJ1833或洛谷2602 [ZJOI2010]数字计数
BZOJ原题链接 洛谷原题链接 又是套记搜模板的时候.. 对\(0\sim 9\)单独统计. 定义\(f[pos][sum]\),即枚举到第\(pos\)位,前面枚举的所有位上是当前要统计的数的个数之 ...
- 【洛谷P2602】数字计数
题目大意:求 [a,b] 中 0-9 分别出现了多少次. 题解:看数据范围应该是一个数位dp. 在 dfs 框架中维护当前的位置和到当前位置一共出现了多少个 \(x,x\in [0,9]\).因此,用 ...
随机推荐
- @总结 - 7@ 生成树计数 —— matrix - tree 定理(矩阵树定理)与 prüfer 序列
目录 @0 - 参考资料@ @0.5 - 你所需要了解的线性代数知识@ @1 - 矩阵树定理主体@ @证明 part - 1@ @证明 part - 2@ @证明 part - 3@ @证明 part ...
- css white-space属性
css white-space属性 规定段落中的文本不进行换行
- uva 11375 Matches (递推)
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&p ...
- 2016 年度开源中国新增开源软件排行榜 TOP 100
2016 年度开源中国新增开源软件排行榜 TOP 100 2016 年度开源中国新增开源软件排行榜 TOP 100 新鲜出炉!本榜单根据 2016 年开源中国新收录的 3030 款软件的关注度和活跃度 ...
- Project Euler Problem 18-Maximum path sum I & 67-Maximum path sum II
基础的动态规划...数塔取数问题. 状态转移方程: dp[i][j] = num[i][j] + max(dp[i+1][j],dp[i+1][j+1]);
- java el表达式报空指针异常(nullpointexception)
最近在使用el表达式的时候,用到了int型变量,因为,很多时候,变量不会被赋初值,后面考虑了下,应该将声明由int 改为integer,改了之后就一直报空指针异常,后面仔细查看,我的getter和se ...
- 【CSS3】loading动画
HTML: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF ...
- H3C NAT ALG
- MySQL之Field 'email' doesn't have a default value问题
MySQL在出现这个Field xxx doesn't have a default value错误的原因是:我们设置了该字段为非空,但是我们没有设置默认值照成的. 比如我们创建一个表: CREATE ...
- 分布式全局唯一ID
方案一.UUID UUID的方式能生成一串唯一随机32位长度数据,它是无序的一串数据,按照开放软件基金会(OSF)制定的标准计算,UUID的生成用到了以太网卡地址.纳秒级时间.芯片ID码和许多可能的数 ...