第一次一道题做了3天才A掉,但是收获还是蛮大的。
鉴于前面刷的模板题都是求区间内有多个满足题意或不满足的题意的,这道题想了很久。
昨天上午想到用和与平方和来一起维护,但是一开始想到用dp[pos][ans1][ans2]表示区间内与7有关的数的平方和,然后用容斥原理。昨天wa了几遍,今天早上才意识到这样写很多地方不能处理,最后改成dp[pos][ans1][ans2]表示区间内与7无关的数的平方和(这样可以直接忽略当前位等于7的情况),好写了很多,然后开始了long long 的溢出情节= =,真是感动
#include <cstdio> #include <algorithm> #include <cstring> using namespace std; typedef long long ll; const int mod = 1000000007; const int N = 25; ll dp[N][8][8],dp2[N][8][8],num[N][8][8],bit[N]; ll log[N]; #define MP pair<pair<ll,ll>,ll> #define fuck pos][ans1][ans2 #define one first.first #define two first.second void init() { log[1] = 1; for(int i = 2; i < N; ++i) log[i] = log[i-1]*10%mod; } MP dfs(int pos,bool flag,int ans1,int ans2) { if(pos == 0) { if(ans1&&ans2) { return make_pair(make_pair(0,0),1); } else return make_pair(make_pair(0,0),0); } if(flag && num[fuck]!= -1) return make_pair(make_pair(dp[fuck],dp2[fuck]),num[fuck]); ll ma = flag ? 9 : bit[pos]; ll x = 0,y = 0, z = 0; MP res; for(int i = 0; i <= ma; ++i) { if(i == 7) continue; res = dfs(pos-1,flag||i<ma,(ans1*10+i)%7,(ans2+i)%7); ll wps = log[pos] * i % mod; x += res.second * wps %mod* wps % mod + wps * 2 * res.two % mod + res.one % mod; y += (res.second * wps%mod + res.two)%mod; z += res.second; } x %= mod;y %= mod;z %= mod; if(flag) { dp[fuck] = x; dp2[fuck] = y; num[fuck] = z; } return make_pair(make_pair(x,y),z); } ll solve(ll n) { int len = 0; ll QAQ = n; while(n) { bit[++len] = n%10; n /= 10; } MP que = dfs(len,0,0,0); ll ans = que.one%mod; return (ans+mod)%mod; } int main() { #ifndef ONLINE_JUDGE freopen("input.txt", "r" ,stdin); #endif // ONLINE_JUDGE ll a,b; memset(num,-1,sizeof(num)); int T; scanf("%d",&T); init(); while(T--) { ll a,b; scanf("%I64d%I64d",&a,&b); ll ans = solve(b)-solve(a-1); printf("%I64d\n",(ans%mod + mod)%mod); } return 0; }