洛谷 P4999 烦人的数学作业

原题链接

数位dp

emmm其实就是个板子题,而且一点坑点都没有

直接看代码吧

别忘了开 \(long \ long\)

#include <iostream>
#include <cstdio>
#include <cstring>

#define ll long long

using namespace std;

const ll mod = 1e9 + 7;
ll l, r, len, T;
ll num[20];
ll dp[20][200][2];	//dp[len][sum][lim]:sum是各位数字之和,18位每一位最大是9,需要开18*9的数组

ll dfs(ll len, ll sum, ll lim){		//这边就是数位dp板子,emm不想写太多注释了,有问题可以去看我的其他博客,或者下面回复就好啦
	if(!len) return sum;
	if(dp[len][sum][lim] != -1) return dp[len][sum][lim];	//记忆化
	ll res = lim ? num[len] : 9;
	ll ans = 0;
	for(ll i = 0; i <= res; i++)
		ans = (ans + dfs(len - 1, sum + i, lim && (i == res))) % mod;	//注意每一次计算都要取模,不然会被卡QWQ
	return dp[len][sum][lim] = ans;
}

ll solve(ll x){
	len = 0;
	while(x){
		num[++len] = x % 10;
		x /= 10;
	}
	memset(dp, -1, sizeof(dp));		//dp初值为-1,防止计算过程中出现答案为0的情况
	return dfs(len, 0, 1) % mod;
}

signed main(){
	scanf("%lld", &T);
	while(T--){
		scanf("%lld%lld", &l, &r);
		printf("%lld\n", (solve(r) - solve(l - 1) + mod) % mod);	//前缀和思想输出答案就好啦
	}
	return 0;
}

完结撒花~