吉哥系列故事——恨7不成妻 数位dp

单身!
  依然单身!
  吉哥依然单身!
  DS级码农吉哥依然单身!
  所以,他生平最恨情人节,不管是214还是77,他都讨厌!
  
  吉哥观察了214和77这两个数,发现:
  2+1+4=7
  7+7=72
  77=7
11
  最终,他发现原来这一切归根到底都是因为和7有关!所以,他现在甚至讨厌一切和7有关的数!

什么样的数和7有关呢?

如果一个整数符合下面3个条件之一,那么我们就说这个整数和7有关——
  1、整数中某一位是7;
  2、整数的每一位加起来的和是7的整数倍;
  3、这个整数是7的整数倍;

现在问题来了:吉哥想知道在一定区间内和7无关的数字的平方和。
Input
输入数据的第一行是case数T(1 <= T <= 50),然后接下来的T行表示T个case;每个case在一行内包含两个正整数L, R(1 <= L <= R <= 10^18)。
Output
请计算[L,R]中和7无关的数字的平方和,并将结果对10^9 + 7 求模后输出。
Sample Input
3
1 9
10 11
17 17
Sample Output
236
221
0
思路:对于一个数可以从中间断开写成aa+bb+2ab的格式,开三个数组,一个记接下来的个数,一个记接下来的平方和,一个记接下来的和,顺着推回去就行了

#include<stdio.h>
#include<cstring>
const int mod=1e9+7;
typedef long long ll;
long long dp[20][10][10],dp1[20][10][10],dp2[20][10][10];
int a[20];
ll p[20];
ll dfs(int pos,int fjia,int fhong,bool limit,ll &ss,ll &dd,ll &cc){
   
	if(pos==-1){
   
		dd=0; ss=0;
		if(fjia!=0&&fhong!=0)	cc=1;
		else cc=0;
		return dd;
	}
	if(!limit&&dp2[pos][fjia][fhong]!=-1){
   
		ss=dp1[pos][fjia][fhong];
		dd=dp2[pos][fjia][fhong];
		cc=dp[pos][fjia][fhong];
		return dp2[pos][fjia][fhong];
	}
	int up=limit?a[pos]:9;
	ss=0,dd=0,cc=0;
	ll s,d,c;
	for(int i=0;i<=up;i++){
   
		if(i==7)	continue;
		dfs(pos-1,(fjia+i)%7,(fhong*10+i)%7,limit&&up==i,s,d,c);
		ll k=i*p[pos]%mod;
		cc=(cc+c)%mod;
		ss=(((c*k%mod)+s)%mod+ss)%mod;
        dd=((c*k%mod*k%mod)%mod+d%mod+2*k*s%mod+dd%mod)%mod;
	}
	if(!limit){
   
        dp1[pos][fjia][fhong]=ss;
        dp[pos][fjia][fhong]=cc;
        dp2[pos][fjia][fhong]=dd;
    }
    return dd;
}
ll solve(ll x){
   
	int pos=0;
	while(x){
   
		a[pos++]=x%10;
		x/=10;	
	}
	ll s,d,c;
	return dfs(pos-1,0,0,true,s,d,c);
}
int main(){
   
	int t;
	memset(dp2,-1,sizeof(dp2));
	scanf("%d",&t);
	p[0]=1;
    for(int i=1;i<20;i++)
        p[i]=p[i-1]*10%mod;
	while(t--){
   
		ll x,y;
		scanf("%lld%lld",&x,&y);
		printf("%lld\n",((solve(y)-solve(x-1))%mod+mod)%mod);
	}
	return 0;
}

全部评论

相关推荐

点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务