LuoGu P1179 数字统计【数位DP】

题目链接
LuoGu P1179 数字统计【数位DP】_第1张图片
这道题的数据范围要暴力很容易,但是如果数据范围变大,比如10^100那么数位dp无疑是最好的,简单的复习一下数位DP。数位DP讲解

#define inf 0x3f3f3f3f
#define ll long long
#define vec vector
//#define P pair
#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
}

你可能感兴趣的:(牛客网&LuoGu练习题)