2018.09.27 hdu4507吉哥系列故事——恨7不成妻(数位dp)

183 篇文章 0 订阅
18 篇文章 0 订阅

传送门
一道比较综合的数位dp。
维护三个值: [ L , R ] [L,R] [L,R] 区间中与7无关的数的数量,与7无关的数之和,与7无关的数的的平方和。
然后可以用第一个值推第二个,第一个和第二个值推第三个。
代码:

#include<bits/stdc++.h>
#define ll long long
#define mod 1000000007
using namespace std;
ll L,R,mul[30];
int t,len,num[20];
struct DP{ll c,s1,s2;}f[30][10][10];
inline DP dfs(int pos,int m1,int m2,bool lim){
	if(pos==0)return (DP){(m1&&m2),0ll,0ll};
	if(~f[pos][m1][m2].c&&!lim)return f[pos][m1][m2];
	DP ret=(DP){0ll,0ll,0ll};
	int up=lim?num[pos]:9;
	for(int i=0;i<=up;++i){
		if(i==7)continue;
		DP tmp=dfs(pos-1,(m1+i)%7,(m2*10+i)%7,lim&&i==up);
		(ret.c+=tmp.c)%=mod;
		(ret.s1+=tmp.s1+tmp.c*mul[pos]%mod*i%mod)%=mod;
		(ret.s2+=((tmp.c*(mul[pos]*mul[pos]%mod)%mod)%mod*i%mod*i%mod+tmp.s2)%mod+tmp.s1*2%mod*mul[pos]%mod*i%mod)%=mod;
	}
	if(!lim)f[pos][m1][m2]=ret;
	return ret;
}
inline ll solve(ll x){
	if(!x)return 0;
	len=0;
	while(x)num[++len]=x%10,x/=10;
	return dfs(len,0,0,1).s2;
}
int main(){
	memset(f,-1,sizeof(f));
	mul[1]=1;
	for(int i=2;i<=20;++i)mul[i]=mul[i-1]*10%mod;
	scanf("%d",&t);
	while(t--)scanf("%lld%lld",&L,&R),printf("%lld\n",((solve(R)-solve(L-1))%mod+mod)%mod);
	return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值