数位dp 数据取余注意事项

AcWing 1086. 恨7不成妻

数位dp例题

注意一个数不能分别对两个不同的数取余,只能将其保存下来

例如下面代码中的prev_b

复制代码
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
LL MOD = 1000000007;
struct AllSum
{
    LL s0, s1, s2;
};
AllSum dp[20][10][7][7];//len head all_digit%7 num%7

LL power10_7[20];
LL power10_MOD[20];
LL power10_no[20];
LL Mod(LL a, LL b)
{
    return (a%b + b) % b;
}
LL Count(LL num)
{
    if (num == 0) return 0;
    LL o = num;
    string nums = to_string(num);
    reverse(nums.begin(), nums.end());
    LL res = 0;
    LL prev_a = 0, prev_b = 0;
    for (int i = nums.size() - 1; i >= 0; i--)
    {
        LL num = nums[i] - '0';
        for (int j = 0; j < num; j++)
        {
            if (j == 7) continue;
            LL s0=0, s1=0, s2=0;
            for (int b = 0; b < 7; b++)
            {
                for (int a = 0; a < 7; a++)
                {
                    LL cur_a = prev_a + a;
                    LL cur_b = prev_b + b;
                    cur_a %= 7;
                    cur_b %= 7;
                    if (cur_a != 0 && cur_b != 0)
                    {
                        s0 += dp[i + 1][j][a][b].s0;
                        s1+= dp[i + 1][j][a][b].s1;
                        s2+= dp[i + 1][j][a][b].s2;
                        s0 %= MOD;
                        s1 %= MOD;
                        s2 %= MOD;
                    }
                }
            }
            res += (prev_b % MOD)*(prev_b%MOD) % MOD*s0%MOD
                + 2 * prev_b%MOD*s1%MOD
                + s2;
            res %= MOD;
            
        }
        if (num == 7) break;
        prev_a = prev_a + num;
        prev_b = prev_b + num*power10_no[i];
        //prev_a %= MOD;
        //prev_b %= MOD;
        if (prev_a%7 != 0 && prev_b%7 != 0 && num!=7&&i == 0)
        {
            res += o%MOD * (o%MOD)%MOD;
        }
    }
    return res%MOD;
}
void YD(LL T)
{
    LL a=T-1, b=T;
    cin >> a >> b;
    cout <<Mod(Count(b) - Count(a - 1), MOD) << endl;




}

int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int T = 1;
    cin >> T;
    for (int i = 0; i < 10; i++)
    {
        if(i!=7)    
            dp[1][i][i % 7][i % 7] = { 1,i,i*i };
    }
    LL power10 = 10;
    for (int i = 2; i < 20; i++,power10*=10)
    {
        for (int j = 0; j < 10; j++)
        {
            if (j == 7) continue;
            for (int a = 0; a < 7; a++)
            {
                for (int b = 0; b < 7; b++)
                {
                    for (int k = 0; k < 10; k++)
                    {
                        if (k == 7) continue;
                        auto &cur = dp[i][j][a][b];
                        auto &prev = dp[i - 1][k][Mod(a-j,7)][Mod(b-j*Mod(power10,7),7)];
                        cur.s0 = (cur.s0 + prev.s0) % MOD;
                        cur.s1 = (cur.s1+(prev.s0*j%MOD*(power10%MOD)%MOD+prev.s1)%MOD)%MOD;
                        cur.s2 = (cur.s2+prev.s0*j%MOD*j%MOD*(power10%MOD)%MOD*(power10%MOD)%MOD 
                            + 2 * j*(power10%MOD)%MOD*prev.s1%MOD 
                            + prev.s2)%MOD;
                    }
                }
            }
        }
    }
    power10_no[0]=power10_7[0] = power10_MOD[0] = 1;
    for (int i = 1; i < 20; i++)
    {
        power10_7[i] = power10_7[i - 1] * 10 % 7;
        power10_MOD[i] = power10_MOD[i - 1] * 10LL % MOD;
        power10_no[i] = power10_no[i - 1] * 10LL ;

    }
    while (T--)
    {
        YD(T);
    }
    return 0;
}
View Code
复制代码

 

posted @   80k  阅读(37)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
点击右上角即可分享
微信分享提示