数位dp板子:记忆化搜索

#include<iostream>
#include<vector>
#include<algorithm>
#include<math.h>
#include<string>
#include<string.h>
#include<iomanip>
#include<map>
#include<queue>
using namespace std;
typedef long long ll;

/*数位dp*/
const int N = 15;
ll dp[N][N];
int num[N], now;
ll dfs(int pos, int sum, bool lead, bool limit)
//pos:第pos位,sum:前面有sum个now,lead:有(true)没有前导零,limit:是(true)不是最高位
{
	ll ans = 0;
	if (pos == 0)return sum;//0位数
	if (!lead and !limit and dp[pos][sum] != -1)return dp[pos][sum];//如果已经记忆了,那就直接返回
	int up = (limit ? num[pos] : 9);//limit:数位限制
	for (int i = 0; i <= up; i++)
	{
		//i在pos的数位上从0~up
		if (i == 0 and lead)ans += dfs(pos - 1, sum, true, limit and i == up);
		//计算000~099
		else if (i == now)ans += dfs(pos - 1, sum + 1, false, limit and i == up);
		//计算200~299
		else if (i != now)ans += dfs(pos - 1, sum, false, limit and i == up);
		//计算100~199
	}
	if (!lead and !limit)dp[pos][sum] = ans;
	return ans;

}
ll solve(ll x)
{
    int len = 0;
	while (x)
	{
		num[++len] = x % 10;
		x /= 10;
	}
	memset(dp, -1, sizeof(dp));
	return dfs(len, 0, true, true);
}
int main()
{
	ll a; ll b;
	cin >> a>>b;
	for (int i = 0; i < 10; i++)now = i, cout << solve(b)-solve(a-1)<<' ';
	return 0;
}```

posted on 2024-03-07 22:04  WHUStar  阅读(7)  评论(0编辑  收藏  举报