数位DP, 继续练习记忆化搜索的数位DP写法,状态转移需要推导一下,
是依据这个性质
(a+b1)^2+(a+b2)^2+...(a+bn)^2 = n*a^2+2*a*(b1+b2+...bn)+b1^2+b2^2+...bn^2
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <queue>
#include <algorithm>
#include <vector>
#include <cstring>
#include <stack>
#include <cctype>
#include <utility>
#include <map>
#include <string>
#include <climits>
#include <set>
#include <string>
#include <sstream>
#include <utility>
#include <ctime>
using std::priority_queue;
using std::vector;
using std::swap;
using std::stack;
using std::sort;
using std::max;
using std::min;
using std::pair;
using std::map;
using std::string;
using std::cin;
using std::cout;
using std::set;
using std::queue;
using std::string;
using std::istringstream;
using std::make_pair;
using std::getline;
using std::greater;
using std::endl;
using std::multimap;
using std::deque;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PAIR;
typedef multimap<int, int> MMAP;
const int MAXN(2010);
const int SIGMA_SIZE(2);
const int MAXM(110);
const int MAXE(300010);
const int MAXH(18);
const int INFI((INT_MAX-1) >> 1);
const int MOD(1000000007);
const ULL LIM(1000000000000000ull);
struct ELE
{
LL qua, suf1, suf2; //从当前状态能够到达合法叶子节点数,后缀的和,后缀的平方和
ELE(LL tq = 0, LL ts1 = 0, LL ts2 = 0): qua(tq), suf1(ts1), suf2(ts2)
{}
};
ELE table[25][7][7][2];
bool vis[25][7][7][2];
LL pow10[25];
int digit[25];
ELE dfs(int len, int st1, int st2, int flag, bool bound)
{
if(len == 0)
if(st1 != 0 && st2 != 0 && flag == 0)
return ELE(1, 0, 0);
else
return ELE(0, 0, 0);
if(!bound && vis[len][st1][st2][flag])
return table[len][st1][st2][flag];
ELE ret, ret2;
int up = bound? digit[len]: 9;
for(int i = 0; i <= up; ++i)
{
ret2 = dfs(len-1, (st1+i)%7, (st2*10+i)%7, flag|(i == 7? 1: 0), bound && i == up);
ret.qua = (ret.qua+ret2.qua)%MOD;
LL temp = i*pow10[len-1]%MOD;
ret.suf1 = (temp*ret2.qua%MOD+ret2.suf1+ret.suf1)%MOD; //利用性质进行转移
ret.suf2 = ( temp*temp%MOD*ret2.qua%MOD
+ret2.suf2+temp*ret2.suf1%MOD*2+ret.suf2)%MOD;
}
if(!bound)
{
vis[len][st1][st2][flag] = true;
table[len][st1][st2][flag] = ret;
}
return ret;
}
LL fun(LL num)
{
int len = 1;
while(true)
{
digit[len] = num%10;
num /= 10;
if(num == 0)
break;
++len;
}
ELE ret = dfs(len, 0, 0, 0, true);
return ret.suf2;
}
int main()
{
memset(vis, 0, sizeof(vis));
pow10[0] = 1;
for(int i = 1; i <= 19; ++i)
pow10[i] = pow10[i-1]*10;
int TC;
scanf("%d", &TC);
while(TC--)
{
LL a, b;
scanf("%I64d%I64d", &a, &b);
printf("%I64d\n", (fun(b)-fun(a-1)+MOD)%MOD);
}
return 0;
}