数位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; }