[Luogu-P4999烦人的数学作业]-数位DP

题目地址

题目意思见原题面。

很容易看出这是个数位DP。

考虑求 l ∼ r l\sim r lr区间内的数,我们可以转化为求 1 ∼ l − 1 1\sim l-1 1l1 1 ∼ r 1\sim r 1r,然后用前缀和的思想相减即可。

此时我们只用考虑上界(下界都为1了),套用数位DP的模板,我们记录一下当前的价值和后面出现了的数的个数即可。

#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const ll Mod=1e9+7;
const int M=30;
struct node{
	ll cnt,val;
	void clear(){cnt=val=0;}
	node(){}
	node(ll a,ll b):cnt(a),val(b){}
}Rec[10][M];
bool vis[10][M];
int B[M],len;
node F(int num,int pos,bool ex){
	if(pos==1) return node(1,num);
	if(!ex&&vis[num][pos]) return Rec[num][pos];
	node now,to;now.clear();
	int r=ex?B[pos-1]:9;
	for(int i=0;i<=r;i++){
		to=F(i,pos-1,ex&&i==r);
		now.val=(now.val+1ll*num*to.cnt%Mod+to.val)%Mod;
		(now.cnt+=to.cnt)%=Mod;
	}	if(!ex){vis[num][pos]=1;Rec[num][pos]=now;}
	return now;
}
ll calc(ll v){
	if(v<=1) return v;
	len=0;
	memset(vis,0,sizeof(vis));
	while(v)B[++len]=v%10,v/=10;
	ll ans=0;
	for(int i=0;i<=B[len];i++){
		(ans+=(F(i,len,i==B[len]).val))%=Mod;
	}	return ans;
}	ll l,r;
int main(){
	int T;for(scanf("%d",&T);T--;){
		scanf("%lld%lld",&l,&r);
		printf("%lld\n",((calc(r)-calc(l-1))%Mod+Mod)%Mod);
	}	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

VictoryCzt

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值