题目链接:吉哥系列故事——恨7不成妻。此题和HDU 3652 B-number这道题很相似,如果题解看不懂,可以先看3652这道题。
代码如下:
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#define mod1 (m+7-(j*(bit[i]%7))%7)%7
#define mod2 (n+7-j%7)%7
using namespace std;
typedef long long ll;
const ll mod = 1000000007;
ll dp1[20][10][2][7][7]; // 个数
ll dp2[20][10][2][7][7]; // 和
ll dp3[20][10][2][7][7]; // 平方和
ll bit[20]; // bit[i] = 10^(i - 1)
ll digit[20];
ll L, R;
void init()
{
memset(dp1, 0, sizeof(dp1));
memset(dp2, 0, sizeof(dp2));
memset(dp3, 0, sizeof(dp3));
memset(bit, 0, sizeof(bit));
bit[1] = 1;
for (int i = 2; i <= 19; i++)
bit[i] = bit[i - 1] * 10;
// 初始化位数为1的情况
for (int i = 0; i <= 9; i++)
{
dp1[1][i][i == 7][i % 7][i % 7] = 1;
dp2[1][i][i == 7][i % 7][i % 7] = i;
dp3[1][i][i == 7][i % 7][i % 7] = i * i;
}
for (int i = 2; i <= 19; i++)
for (int j = 0; j <= 9; j++)
for (int k = 0; k <= 1; k++)
for (int m = 0; m <= 6; m++)
for (int n = 0; n <= 6; n++)
for (int t = 0; t <= 9; t++)
{
if (!k && j == 7)
continue;
dp1[i][j][k][m][n]+=dp1[i-1][t][k][mod1][mod2];
dp1[i][j][k][m][n]%=mod;
dp2[i][j][k][m][n]+=dp2[i-1][t][k][mod1][mod2]+((j*(bit[i]%mod))%mod*dp1[i-1][t][k][mod1][mod2])%mod;
dp2[i][j][k][m][n]%=mod;
dp3[i][j][k][m][n]+=((((j*(bit[i]%mod))%mod)*((j*(bit[i]%mod))%mod))%mod*dp1[i-1][t][k][mod1][mod2])%mod
+((2*j*(bit[i]%mod))%mod*dp2[i-1][t][k][mod1][mod2])%mod+dp3[i - 1][t][k][mod1][mod2];
dp3[i][j][k][m][n]%=mod;
if (k && j == 7)
{
dp1[i][j][k][m][n]+=dp1[i-1][t][!k][mod1][mod2];
dp1[i][j][k][m][n]%=mod;
dp2[i][j][k][m][n]+=dp2[i-1][t][!k][mod1][mod2]+(((j*(bit[i]%mod))%mod)*dp1[i-1][t][!k][mod1][mod2])%mod;
dp2[i][j][k][m][n]%=mod;
dp3[i][j][k][m][n]+=((((j*(bit[i]%mod))%mod)*((j*(bit[i]%mod))%mod))%mod*dp1[i-1][t][!k][mod1][mod2])%mod
+((2*j*(bit[i]%mod))%mod*dp2[i-1][t][!k][mod1][mod2])%mod+dp3[i - 1][t][!k][mod1][mod2];
dp3[i][j][k][m][n]%=mod;
}
}
}
ll cal(ll n)
{
memset(digit, 0, sizeof(digit));
int len = 0;
while (n)
{
digit[++len] = n % 10;
n /= 10;
}
ll ans = 0;
ll num = 0; // num为前缀模mod的值
ll sum = 0, preffix = 0; // suffix为前缀模7的值,sum为前缀各位数字相加模7的值
for (int i = len; i >= 1; i--)
{
for (int j = 0; j < digit[i]; j++)
{
if (j == 7)
continue;
int m1 = (7 - preffix % 7) % 7, m2 = (7 - sum % 7) % 7;
for (int m = 0; m <= 6; m++)
for (int n = 0; n <= 6; n++)
{
if (m != m1 && n != m2)
{
ans += ((num*num)%mod*dp1[i][j][0][m][n])%mod+((2*num)%mod*dp2[i][j][0][m][n])%mod+dp3[i][j][0][m][n];
ans %= mod;
}
}
}
num += digit[i] * (bit[i] % mod);
num %= mod;
preffix += digit[i] * (bit[i] % 7);
preffix %= 7;
sum += digit[i];
if (digit[i] == 7)
break;
}
return ans;
}
int main()
{
//freopen("test.txt", "r", stdin);
int T;
scanf("%d", &T);
init();
while (T--)
{
scanf("%I64d%I64d", &L, &R);
printf("%I64d\n", (cal(R + 1) - cal(L) + mod) % mod);
}
return 0;
}