HDU 4507 吉哥系列故事——恨7不成妻 数位dp

来源:互联网 发布:mac office 破解版 编辑:程序博客网 时间:2024/05/18 17:58

题目链接:吉哥系列故事——恨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)%7using 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;}




阅读全文
0 0
原创粉丝点击