单身!
依然单身!
吉哥依然单身!
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无关的数字的平方和。
3 1 9 10 11 17 17
236 221 0
题目大意:求指定范围内与7不沾边的所有数的平方和。结果要mod 10^9+7(鬼畜の元凶)
解题思路:
与7不沾边的数需要满足三个条件。
①不出现7
②各位数和不是7的倍数
③这个数不是7的倍数
这三个条件都是基础的数位DP。
但是这题要统计的不是符合条件个数,而是平方和。
也就是说在DP时候,要重建每个数,算出平方,然后求和。
需要维护三个值(推荐使用结构体), 假定dfs推出返回的结构体是next,当前结果的结构体是ans
①符合条件数的个数 cnt
②符合条件数的和 sum
③符合添加数的平方和 sqsum
其中①是基础数位DP。②next.sum+(10^len*i)*ans.cnt,其中(10^len*i)*ans.cnt代表以len为首位的这部分数字和。
③首先重建一下这个数,(10^len*i+x),其中x是这个数的后面部分,则平方和就是(10^len*i)^2+x^2+2*10^len*i*x,其中x^2=next.sqsum
整体还要乘以next.cnt,毕竟不止一个。
这样sqsum+=next.sqsum
sqsum+=(2*10^len*i*x)*next.cnt=(2*10^len*i)*next.sum(神奇的化简)
sqsum+=(10^len*i)^2*next.cnt
然后就是本题鬼畜的地方了,cnt,sum,sqsum,三个都是达到了int64极限。
也即是说凡是这三个值参与运算的地方,都要狠狠打上mod,尤其是cnt!一坨坨mod出现了。
mod之后统计函数也有个小陷阱,那就是f(r)在mod之后有可能小于f(l-1)。也就是要对负数取正数模。
负数取模的方法(ans%mod+mod)%mod。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;
const ll mod = 1e9 + 7;
struct node
{
ll cnt;
ll sum;
ll ret;
}dp[20][10][7][7][2];
ll pow10[22];
int b[22];
node dfs(int pos,int pre,int r1,int r2,int statue,int limit)
{
int i,j;
if(pos<0) {
node t={1,0,0};
if(r1==0 || r2==0 || statue==1) t.cnt=0;
return t;
}
if(!limit && dp[pos][pre][r1][r2][statue].cnt!=-1) return dp[pos][pre][r1][r2][statue];
int end=limit?b[pos]:9;
node ans={0,0,0};
for(i=0;i<=end;i++) {
node next = dfs(pos-1,i,(r1+i)%7,(r2*10+i)%7,statue||i==7,limit && i==end);
ans.cnt+=next.cnt;
ans.cnt%=mod;
ans.sum+=(next.sum+((pow10[pos]*i)%mod)*next.cnt%mod)%mod;
ans.sum%=mod;
ans.ret+=(next.ret+((2*pow10[pos]*i)%mod)*next.sum)%mod;
ans.ret%=mod;
ans.ret+=((next.cnt*pow10[pos])%mod*pow10[pos]%mod*i*i%mod);
ans.ret%=mod;
}
if(!limit) dp[pos][pre][r1][r2][statue]=ans;
return ans;
}
ll work(ll num)
{
int cnt=0;
memset(b,0,sizeof(b));
while(num) {
b[cnt++]=num%10;
num/=10;
}
node tmp = dfs(cnt-1,9,0,0,0,1);
return tmp.ret;
}
int main()
{
int T,i,j;
ll l,r;
memset(dp,-1,sizeof(dp));
pow10[0]=1;
for(i=1;i<=18;i++) {
pow10[i]=pow10[i-1]*10%mod;
}
cin>>T;
while(T--) {
cin>>l>>r;
ll ans = (work(r)-work(l-1)+mod)%mod;
cout<<ans<<endl;
}
return 0;
}