Title
吉哥系列故事——恨7不成妻
Description
单身!
依然单身!
吉哥依然单身!
DS级码农吉哥依然单身!
所以,他生平最恨情人节,不管是214还是77,他都讨厌!
吉哥观察了214和77这两个数,发现:
2+1+4=7
7+7=7*2
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
题解:
一道……很毒瘤的数位dp。
我们可以定义一个结构体,用cnt表示符合要求的个数,sum表示这些数的和,sqsum表示平方和。
cnt很简单,一个朴素的数位dp。
sum可以用cnt表示。
这个数就是10^pos*i+x x表示这个数的后面部分。
则平方和就应该加
(10^pos*i+x)^2=(10^pos*i)^2+2*(10^pos*i*x+x^2
但是现在后面有一堆数。
即sum=10^pos*i+x1+10^pos*2+x2+…+10^pos*i+xn
=10^pos*i*cnt+(x1+x2+…+xn)
//cnt表示数的数量,而后面的一坨表示这一位的下一位的和。
同理,sqsum=(10^pos*i)^2*cnt+2*10^pos*i*(x1+x2+…+xn)+(x1^2+x2^2+…+性能……2)
用u表示之后的位的答案。
ans.sum=(10^pos*i)*u.cnt+u.sum;
ans.sqsum=(10^pos*i)^2*u.cnt+2*10^pos*i*u.sum+u.sqsum;
取模有毒。
而且我踏马一开始还看错了模数。
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int N = 20;
const int M = 10;
const int MOD = 1e9+7;
int t;
int a[N];
ll mpow[N];
struct node{
ll cnt,sum,sqsum;
node() {cnt=-1;sum=sqsum=0;}
void unit(){
cnt=sum=sqsum=0;
}
}dp[N][M][M];
node dfs(int pos,int mod,int sum,bool zero,bool limit){
if(pos==-1){
node u;u.cnt=(mod&&sum);
u.sum=0,u.sqsum=0;
return u;
}
if(!zero&&!limit&&dp[pos][mod][sum].cnt!=-1)
return dp[pos][mod][sum];
int mx;if(limit) mx=a[pos];else mx=9;
node ans;ans.unit();
for(int i=0;i<=mx;i++){
if(i==7) continue;
node u=dfs(pos-1,(mod*10+i)%7,(sum+i)%7,zero&&i==0,limit&&i==mx);
ans.cnt=(ans.cnt+u.cnt)%MOD;
//ans.cnt%=MOD;
ll a=mpow[pos];
ans.sum+=(u.sum+((a*i)%MOD)*u.cnt%MOD)%MOD;
ans.sum%=MOD;
ans.sqsum+=(u.sqsum+((2*a*i)%MOD)*u.sum)%MOD;
ans.sqsum%=MOD;
ans.sqsum+=((u.cnt*a)%MOD*a%MOD*i*i%MOD);
ans.sqsum%=MOD;
/* ans.sum=((ans.sum+i*a%MOD)*u.cnt%MOD)%MOD;
ans.sum=(ans.sum+u.sum)%MOD;
ans.sqsum=(ans.sqsum+((a*i)%MOD*(a*i%MOD)*(u.cnt%MOD))%MOD);
ans.sqsum=(ans.sqsum+(2*a*i%MOD*u.sum)%MOD)%MOD;
ans.sqsum=(ans.sqsum+(u.sqsum%MOD))%MOD;*/
}
if(!limit&&!zero) dp[pos][mod][sum]=ans;
return ans;
}
ll l,r;
ll getans(ll x){
int cnt=0;
while(x){
a[cnt++]=x%10;
x/=10;
}
return dfs(cnt-1,0,0,1,1).sqsum;
}
int main(){
mpow[0]=1;
for(int i=1;i<=18;i++) mpow[i]=(mpow[i-1]*10)%MOD;
scanf("%d",&t);
while(t--){
cin>>l>>r;
ll ans=getans(r);
ans-=getans(l-1);
cout<<(ans%MOD+MOD)%MOD<<endl;
}
return 0;
}