[P2602] [ZJOI2010]数字计数(数位dp)
作者:互联网
原题
题目描述
给定两个正整数 \(a\) 和 \(b\),求在 \([a,b]\) 中的所有整数中,每个数码(digit)各出现了多少次。
输入格式
仅包含一行两个整数 \(a,b\),含义如上所述。
输出格式
包含一行十个整数,分别表示 \(0∼9\)在 \([a,b]\)中出现了多少次。
输入输出样例
输入 #1
1 99
输出 #1
9 20 20 20 20 20 20 20 20 20
说明/提示
数据规模与约定
- 对于 \(30\%\) 的数据,保证 \(a≤b≤10^6\);
- 对于 \(100\%\) 的数据,保证 \(1≤a≤b≤10^{12}\)。
思路
数位dp套模板,注意前导零。
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <list>
#include <map>
#include <iostream>
#include <iomanip>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <unordered_map>
#include <vector>
#define LL long long
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f
#define PI 3.1415926535898
#define F first
#define S second
#define endl '\n'
#define lson rt << 1
#define rson rt << 1 | 1
#define lowbit(x) (x & (-x))
#define f(x, y, z) for (int x = (y), __ = (z); x < __; ++x)
#define _rep(i, a, b) for (int i = (a); i <= (b); ++i)
#define _per(i, a, b) for (int i = (a); i >= (b); --i)
using namespace std;
LL dp[20][20];
LL l, r;
int a[20], tar;
inline LL dfs(int pos, int cnt, bool lead, bool limit)
{
if (pos == -1)
return cnt;
if (!limit && !lead && dp[pos][cnt] != -1)
return dp[pos][cnt];
int up = limit ? a[pos] : 9;
LL ans = 0;
for (int i = 0; i <= up; i++)
{
ans += dfs(pos - 1, cnt + ((!lead || i) && (i == tar)), lead && (i == 0), limit && (i == a[pos]));
}
if (!limit && !lead)
dp[pos][cnt] = ans;
return ans;
}
inline LL solve(LL x, int num)
{
memset(dp, -1, sizeof(dp));
tar = num;
int pos = 0;
while (x)
{
a[pos++] = x % 10;
x /= 10;
}
a[pos] = 0;
return dfs(pos - 1, 0, true, true);
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cin >> l >> r;
_rep(i, 0, 9)
{
cout << solve(r, i) - solve(l - 1, i) << " ";
}
}
标签:20,int,LL,pos,ZJOI2010,P2602,include,dp,define 来源: https://www.cnblogs.com/hfcdyp/p/14136847.html