BZOJ 2757: [SCOI2012]Blinker的仰慕者 数位DP

本文介绍了一种使用数位动态规划(DP)的方法来解决特定因子和的问题,该方法可以有效地处理大规模整数范围内的求和问题,特别适用于因子分解中涉及2、3、5和7的情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

好繁琐,因为难处理,分为k==0和k!=0两类处理。

代码很丑。。。手残伤不起。。。

//#pragma comment(linker, "/STACK:102400000,102400000")
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<cmath>
#include<cctype>
#include<string>
#include<algorithm>
#include<iostream>
#include<ctime>
#include<map>
#include<set>
using namespace std;
#define MP(x,y) make_pair((x),(y))
#define PB(x) push_back(x)
typedef long long LL;
//typedef unsigned __int64 ULL;
/* ****************** */
const int INF=100011122;
const double INFF=1e100;
const double eps=1e-8;
const int mod=20120427;
const int NN=1005;
const int MM=1000010;
/* ****************** */

//保证没有0
int sum[19][55][37][19][19];
int dp[19][55][37][19][19];
LL pp10[20];
int a[20];
int jian[10][4];

//用于计算k==0
LL dp0[20][3];
LL sum0[20][3];
/*
0:有中间0
1:只有前导0
2:无0
*/

void INC(int &a,LL b)
{
    b%=mod;
    a+=b;
    if(a>=mod)
        a-=mod;
}

void init(int n)
{
    int i,j1,j2,j3,j4;
    LL t,tt;

    memset(sum,0,sizeof(sum));
    memset(dp,0,sizeof(dp));

    memset(dp0,0,sizeof(dp0));
    memset(sum0,0,sizeof(sum0));

    //0
    jian[0][0]=0;
    jian[0][1]=0;
    jian[0][2]=0;
    jian[0][3]=0;
    //1
    jian[1][0]=0;
    jian[1][1]=0;
    jian[1][2]=0;
    jian[1][3]=0;
    //2
    jian[2][0]=1;
    jian[2][1]=0;
    jian[2][2]=0;
    jian[2][3]=0;
    //3
    jian[3][0]=0;
    jian[3][1]=1;
    jian[3][2]=0;
    jian[3][3]=0;
    //4
    jian[4][0]=2;
    jian[4][1]=0;
    jian[4][2]=0;
    jian[4][3]=0;
    //5
    jian[5][0]=0;
    jian[5][1]=0;
    jian[5][2]=1;
    jian[5][3]=0;
    //6
    jian[6][0]=1;
    jian[6][1]=1;
    jian[6][2]=0;
    jian[6][3]=0;
    //7
    jian[7][0]=0;
    jian[7][1]=0;
    jian[7][2]=0;
    jian[7][3]=1;
    //8
    jian[8][0]=3;
    jian[8][1]=0;
    jian[8][2]=0;
    jian[8][3]=0;
    //9
    jian[9][0]=0;
    jian[9][1]=2;
    jian[9][2]=0;
    jian[9][3]=0;

    pp10[0]=1;
    for(i=1;i<=19;i++)
    {
        pp10[i]=pp10[i-1]*10%mod;
    }

    dp0[0][2]=1;
    for(i=0;i<n;i++)
    {
        if(dp0[i][0] || sum0[i][0])
        {
            dp0[i+1][0]+=dp0[i][0]*10;
            dp0[i+1][0]%=mod;
            sum0[i+1][0]+=sum0[i][0]*10;
            t=(LL)(dp0[i][0]*45%mod)*pp10[i];
            t%=mod;
            sum0[i+1][0]+=t;
            sum0[i+1][0]%=mod;
        }
        if(dp0[i][1] || sum0[i][1])
        {
            //0
            dp0[i+1][1]+=dp0[i][1];
            dp0[i+1][1]%=mod;
            sum0[i+1][1]+=sum0[i][1];
            sum0[i+1][1]%=mod;
            //!0
            dp0[i+1][0]+=dp0[i][1]*9;
            dp0[i+1][0]%=mod;
            sum0[i+1][0]+=sum0[i][1]*9;
            t=(LL)(dp0[i][1]*45%mod)*pp10[i];
            t%=mod;
            sum0[i+1][0]+=t;
            sum0[i+1][0]%=mod;
        }
        if(dp0[i][2] || sum0[i][2])
        {
            //0
            dp0[i+1][1]+=dp0[i][2];
            dp0[i+1][1]%=mod;
            sum0[i+1][1]+=sum0[i][2];
            sum0[i+1][1]%=mod;
            //!0
            dp0[i+1][2]+=dp0[i][2]*9;
            dp0[i+1][2]%=mod;
            sum0[i+1][2]+=sum0[i][2]*9;
            t=(LL)(dp0[i][2]*45%mod)*pp10[i];
            t%=mod;
            sum0[i+1][2]+=t;
            sum0[i+1][2]%=mod;
        }
    }

    dp[0][0][0][0][0]=1;
    for(i=0;i<n;i++)
        for(j1=0;j1<=54;j1++)
            for(j2=0;j2<=36;j2++)
                for(j3=0;j3<=18;j3++)
                    for(j4=0;j4<=18;j4++)
                    {
                        if(dp[i][j1][j2][j3][j4] || sum[i][j1][j2][j3][j4])
                        {
                            t=dp[i][j1][j2][j3][j4];
                            tt=sum[i][j1][j2][j3][j4];
                            //1
                            dp[i+1][j1][j2][j3][j4]+=t;
                            dp[i+1][j1][j2][j3][j4]%=mod;
                            INC(sum[i+1][j1][j2][j3][j4],tt);
                            INC(sum[i+1][j1][j2][j3][j4],t*pp10[i]);
                            //2
                            dp[i+1][j1+1][j2][j3][j4]+=t;
                            dp[i+1][j1+1][j2][j3][j4]%=mod;
                            INC(sum[i+1][j1+1][j2][j3][j4],tt);
                            INC(sum[i+1][j1+1][j2][j3][j4],t*pp10[i]*2);
                            //3
                            dp[i+1][j1][j2+1][j3][j4]+=t;
                            dp[i+1][j1][j2+1][j3][j4]%=mod;
                            INC(sum[i+1][j1][j2+1][j3][j4],tt);
                            INC(sum[i+1][j1][j2+1][j3][j4],t*pp10[i]*3);
                            //4
                            dp[i+1][j1+2][j2][j3][j4]+=t;
                            dp[i+1][j1+2][j2][j3][j4]%=mod;
                            INC(sum[i+1][j1+2][j2][j3][j4],tt);
                            INC(sum[i+1][j1+2][j2][j3][j4],t*pp10[i]*4);
                            //5
                            dp[i+1][j1][j2][j3+1][j4]+=t;
                            dp[i+1][j1][j2][j3+1][j4]%=mod;
                            INC(sum[i+1][j1][j2][j3+1][j4],tt);
                            INC(sum[i+1][j1][j2][j3+1][j4],t*pp10[i]*5);
                            //6
                            dp[i+1][j1+1][j2+1][j3][j4]+=t;
                            dp[i+1][j1+1][j2+1][j3][j4]%=mod;
                            INC(sum[i+1][j1+1][j2+1][j3][j4],tt);
                            INC(sum[i+1][j1+1][j2+1][j3][j4],t*pp10[i]*6);
                            //7
                            dp[i+1][j1][j2][j3][j4+1]+=t;
                            dp[i+1][j1][j2][j3][j4+1]%=mod;
                            INC(sum[i+1][j1][j2][j3][j4+1],tt);
                            INC(sum[i+1][j1][j2][j3][j4+1],t*pp10[i]*7);
                            //8
                            dp[i+1][j1+3][j2][j3][j4]+=t;
                            dp[i+1][j1+3][j2][j3][j4]%=mod;
                            INC(sum[i+1][j1+3][j2][j3][j4],tt);
                            INC(sum[i+1][j1+3][j2][j3][j4],t*pp10[i]*8);
                            //9
                            dp[i+1][j1][j2+2][j3][j4]+=t;
                            dp[i+1][j1][j2+2][j3][j4]%=mod;
                            INC(sum[i+1][j1][j2+2][j3][j4],tt);
                            INC(sum[i+1][j1][j2+2][j3][j4],t*pp10[i]*9);
                        }
                    }
    dp[0][0][0][0][0]=0;
    for(i=2;i<=n;i++)
        for(j1=0;j1<=54;j1++)
            for(j2=0;j2<=36;j2++)
                for(j3=0;j3<=18;j3++)
                    for(j4=0;j4<=18;j4++)
                    {
                        dp[i][j1][j2][j3][j4]+=dp[i-1][j1][j2][j3][j4];
                        if(dp[i][j1][j2][j3][j4]>=mod)
                            dp[i][j1][j2][j3][j4]-=mod;
                        sum[i][j1][j2][j3][j4]+=sum[i-1][j1][j2][j3][j4];
                        if(sum[i][j1][j2][j3][j4]>=mod)
                            sum[i][j1][j2][j3][j4]-=mod;
                    }
}
LL dfs_sum(int pos,int n1,int n2,int n3,int n4,LL t_sum,bool fg,bool allzero)
{
    if(pos==0)
    {
        if(n1==0 && n2==0 && n3==0 && n4==0)
            return t_sum;
        return 0;
    }
    if(!fg)
    {
        if(allzero)
        {
            return sum[pos][n1][n2][n3][n4];
        }
        else
        {
            LL temp=sum[pos][n1][n2][n3][n4]-sum[pos-1][n1][n2][n3][n4];
            if(temp<0)temp+=mod;
            LL temp1=dp[pos][n1][n2][n3][n4]-dp[pos-1][n1][n2][n3][n4];
            if(temp1<0)temp1+=mod;
            temp+=t_sum*temp1;
            temp%=mod;
            return temp;
        }
    }
    int i;
    LL ans=0;
    if(allzero)
        i=0;
    else
        i=1;
    for(;i<=a[pos];i++)
    {
        int m1=n1-jian[i][0];
        int m2=n2-jian[i][1];
        int m3=n3-jian[i][2];
        int m4=n4-jian[i][3];
        if(m1>=0 && m2>=0 && m3>=0 && m4>=0)
        {
            ans+=dfs_sum(pos-1,m1,m2,m3,m4,(t_sum+i*pp10[pos-1])%mod,i==a[pos],allzero&&(i==0));
            if(ans>=mod)
                ans-=mod;
        }
    }
    return ans;
}
LL calc(LL x,int n1,int n2,int n3,int n4)
{
    int tol=0;
    do
    {
        a[++tol]=x%10;
        x/=10;
    }while(x);
    return dfs_sum(tol,n1,n2,n3,n4,0,1,1);
}
LL solve(LL st,LL en,int n1,int n2,int n3,int n4)
{
    LL ans=calc(en,n1,n2,n3,n4)-calc(st-1,n1,n2,n3,n4);
    if(ans<0)ans+=mod;
    return ans;
}

LL dfs_zero_sum(int pos,LL t_sum,bool ok,bool fg,bool allzero)
{
    if(pos==0)
    {
        if(ok)return t_sum;
        return 0;
    }
    if(!fg)
    {
        if(ok)
        {
            LL temp=pp10[pos-1]*(pp10[pos]-1)*5;
            temp%=mod;
            if(temp<0)temp+=mod;
            temp+=t_sum*pp10[pos];
            temp%=mod;
            return temp;
        }
        else
        {
            LL temp=sum0[pos][0];
            temp+=t_sum*dp0[pos][0];
            temp%=mod;
            if(!allzero)
            {
                temp+=sum0[pos][1];
                temp%=mod;
                temp+=t_sum*dp0[pos][1]%mod;
                temp%=mod;
            }
            return temp;
        }
    }
    int i;
    LL ans=0;
    bool ok1;
    for(i=0;i<=a[pos];i++)
    {
        ok1=ok;
        if(i==0 && !allzero)
            ok1=true;

        ans+=dfs_zero_sum(pos-1,(t_sum+i*pp10[pos-1])%mod,ok1,i==a[pos],allzero&&(i==0));
        if(ans>=mod)
            ans-=mod;
    }
    return ans;
}

LL calc_zero(LL x)
{
    int tol=0;
    do
    {
        a[++tol]=x%10;
        x/=10;
    }while(x);
    return dfs_zero_sum(tol,0,0,1,1);
}

void solve_zero(LL st,LL en)
{
    LL ans=calc_zero(en)-calc_zero(st-1);
    if(ans<0)ans+=mod;
    printf("%lld\n",ans);
}

int main()
{
    init(18);
    int cas;
    int n1,n2,n3,n4;
    LL st,en,k,ans;
    scanf("%d",&cas);
    while(cas--)
    {
        scanf("%lld%lld%lld",&st,&en,&k);
        if(k==0)
        {
            solve_zero(st,en);
            continue;
        }
        n1=n2=n3=n4=0;
        while(k%2==0)
        {
            n1++;
            k/=2;
        }
        while(k%3==0)
        {
            n2++;
            k/=3;
        }
        while(k%5==0)
        {
            n3++;
            k/=5;
        }
        while(k%7==0)
        {
            n4++;
            k/=7;
        }
        if(k>1 || n1>54 || n2>36 || n3>18 || n4>18)
        {
            ans=0;
        }
        else
        {
            ans=solve(st,en,n1,n2,n3,n4);
        }
        printf("%lld\n",ans);
    }
    return 0;
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值