LuoGu P1179 数字统计【数位DP】

题目链接
在这里插入图片描述
这道题的数据范围要暴力很容易,但是如果数据范围变大,比如10^100那么数位dp无疑是最好的,简单的复习一下数位DP。数位DP讲解

#define inf 0x3f3f3f3f
#define ll long long
#define vec vector<int>
//#define P pair<int,string>
#define MAX 105

int L, R, dp[10][10];//dp[i][j]:i位数,最高位为j时有多少2

int cal(string n) {
	int res = 0, l = n.size();
	for (int i = 1; i < n[0] - '0'; i++)//加上最高位比它小的
		res += dp[l][i];

	for (int i = 1; i < l; i++)
		for (int j = 1; j < 10; j++)
			res += dp[i][j];//加上位数比他少的,最高位不能为0

	//最高位一致,低位比她小
	for (int i = l - 1; i >= 1; i--) {
		for (int j = 0; j < n[l - i] - '0'; j++) {//最高位固定,后面的每一位取小于关系
			res += dp[i][j];
			if (n[0] == '2')res += pow(10, i - 1);
		}
	}
	return res;
}

int main() {
	memset(dp, 0, sizeof(dp)); dp[1][2] = 1;
	for (int i = 2; i < 10; i++)
		for (int j = 0; j < 10; j++) {
			if (j == 2)dp[i][j] = pow(10, i - 1);//20的话有 20-29 10个加上上一位的
			for (int k = 0; k < 10; k++)
				dp[i][j] += dp[i - 1][k];
		}
	cin >> L >> R;
	string r = to_string(R + 1), l = to_string(L);
	cout << cal(r) - cal(l) << endl;//传入的是R+1
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值