P2602 [ZJOI2010] 数字计数:数位DP

https://www.luogu.com.cn/problem/P2602

// #include <iostream>
// #include <iomanip>
// #include <unistd.h>
// #include <climits>
// #include <string>
// #include <stdlib.h>
// #include <cstdio>
// #include <fcntl.h>
#include <iostream>
#include <cmath>
#include <vector>
using namespace std;
typedef long long ll;

ll num(vector<int>& data, int pos)
{
	ll t = 0;
	while(pos >= 0)
	{
		t *= 10;
		t += data[pos--];
	}
	return t;
}

ll dfs(vector<vector<vector<ll>>>& dp,
	vector<int>& data, int pos, int x, bool limit, bool zero)
{
	if(pos == -1)	//没有数字,贡献x零次
		return 0;
	if(dp[pos][limit][zero] != -1)
		return dp[pos][limit][zero];
	int up = limit ? data[pos] : 9;
	ll ret = 0;
	for(int i = 0; i<=up; ++i)
	{
		ret += dfs(dp, data, pos-1, x, limit&&i==data[pos], zero&&i==0);	//不管什么情况都要计算后边贡献x的次数

		//当当前位置等于x,要计算当前位置贡献x的次数
		if(i == x)
		{
			if(limit && i==data[pos])	//limit的情况下不可能有前导零
				ret += num(data, pos-1) + 1;
			else if(!(zero && i==0))	//当有前导零并且当前位置也是0,就不加pow(10, pos);
				ret += pow(10, pos);
		}
	}
	return dp[pos][limit][zero] = ret;
}

ll solve(ll a, int x)
{
	vector<int> data(0);
	while (a)
	{
		data.push_back(a%10);
		a/=10;
	}
	int len = data.size();
	vector<vector<vector<ll>>> dp(len, vector<vector<ll>>(2, vector<ll>(2, -1)));
	return dfs(dp, data, len-1, x, true, true);
}
int main()
{
	ll L, R;
	cin >> L >> R;
	if(L > R) swap(L,R);
	
	for(int i = 0; i < 10; ++i)
	{
		cout << solve(R, i) - solve(L-1, i)  << (i==9?"":" ");
	}
	return 0;
}
posted @   hellozhangjz  阅读(9)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示