hdu4507【数位dp】

程序猿的悲哀。。

数位dp



#include <cmath>
#include <cstdio>
#include <cstring>
#define LL long long
#define MOD 1000000007LL
using namespace std;

LL dp1[20][10][7][7][2];
LL dp2[20][10][7][7][2];
LL cnt[20][10][7][7][2];

LL a[20],b[20],c[20];
LL B,C;
LL m10 (LL x) {
	LL t = 1;
	for(;x;--x)
		t = t * 10 % MOD;
	return t;
}
void dfs (LL u,LL la,LL mods,LL smds,LL lim) {
	if(u == 0) {
			dp1[u][la][mods][smds][lim] = 0;
			dp2[u][la][mods][smds][lim] = 0;
			cnt[u][la][mods][smds][lim] = 0;
		if(mods != 0 && smds != 0) {
			cnt[u][la][mods][smds][lim]++;
		}
		return;
	}
	if(cnt[u][la][mods][smds][lim] != -1) {
		return;
	}	
		cnt[u][la][mods][smds][lim] = 0;
		dp1[u][la][mods][smds][lim] = 0;
		dp2[u][la][mods][smds][lim] = 0;
	LL ed = lim ? a[u] : 9LL;
	
	for(LL i = 0;i <= ed;++i) {
		if(i == 7LL)
			continue;
		int d = lim && i == a[u];
		dfs(u - 1,i,(mods * 10 + i) % 7,(smds + i) % 7,d);

		cnt[u][la][mods][smds][lim] = (cnt[u][la][mods][smds][lim] + cnt[u - 1][i][(mods * 10 + i) % 7][(smds + i) % 7][d]) % MOD;
		dp1[u][la][mods][smds][lim] = (dp1[u][la][mods][smds][lim] + (cnt[u - 1][i][(mods * 10 + i) % 7][(smds + i) % 7][d] * i * m10(u - 1)) % MOD + dp1[u - 1][i][(mods * 10 + i) % 7][(smds + i) % 7][d]) % MOD;
		dp2[u][la][mods][smds][lim] = (dp2[u][la][mods][smds][lim] + (((cnt[u - 1][i][(mods * 10 + i) % 7][(smds + i) % 7][d] * i * i)%MOD * (m10(2 * u - 2) % MOD)) % MOD + (2 * i * m10(u - 1) %MOD * dp1[u - 1][i][(mods * 10 + i) % 7][(smds + i) % 7][d]) % MOD + dp2[u - 1][i][(mods * 10 + i) % 7][(smds + i) % 7][d])) % MOD;
	}
	return ;
	
}

int main () {
	
	int T;
	scanf("%d",&T);
	
	while(T--) {
		memset(dp1,-1,sizeof dp1);
		memset(dp2,-1,sizeof dp2);
		memset(cnt,-1,sizeof cnt);
		
		scanf("%I64d %I64d",&B,&C);
		--B;
		
	
		LL lb = log10(B) + 1;
		LL bb = B;
		for(LL i = 1;B;++i) {
			b[i] = B % 10;
			B /= 10;
		}
		
		LL lc = log10(C) + 1;
		for(LL i = 1;C;++i) {
			c[i] = C % 10;
			C /= 10;
		}
		
		
		LL t1;
		if(bb) {
			for(LL i = 1;i <= lb;++i) {
				a[i] = b[i];
			}
			dfs(lb,0,0,0,1);
			t1 = dp2[lb][0][0][0][1];
		}
		else t1 = 0;
		memset(dp1,-1,sizeof dp1);
		memset(dp2,-1,sizeof dp2);
		memset(cnt,-1,sizeof cnt);
		for(LL i = 1;i <= lc;++i) {
			a[i] = c[i];
		}
		dfs(lc,0,0,0,1);
		LL t2 = dp2[lc][0][0][0][1];
		printf("%I64d\n",(t2 - t1 < 0) ? (t2 - t1 + MOD) : (t2 - t1));
	}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值