[数位dp] hihoCoder 1033 交错和

题意:

问你[l,r]区间内的所有满足各个位一加一减最后和是k的全有数的和。

思路:

数位dp

dp[site][sum][p][k] 代表site位,和是sum,当前是加还是减,最后和是k的数的和以及个数

也就是存成结构体。

然后求的时候

ans.cnt=(ans.cnt+cur.cnt)%mod;
ans.sum=(ans.sum+cur.sum+cur.cnt*tep)%mod;
tep为i*当前位的位权。

代码:

#include"cstdlib"
#include"cstdio"
#include"cstring"
#include"cmath"
#include"queue"
#include"algorithm"
#include"iostream"
#include"map"
#define mod 1000000007
#define ll long long
using namespace std;
struct node
{
    ll cnt,sum;
    node()
    {
        cnt=-1;
        sum=0;
    }
} dp[22][402][2][202];
int num[22],k;
ll ten[22];
ll l,r;
node dfs(int site,int sum,int p,int f,int zero)
{
    if(site==0)
    {
        node a;
        if( zero==1 || sum!=k+200) a.cnt=0;
        else a.cnt=1;
        return a;
    }
    if(!f && !zero && dp[site][sum][p][k].cnt!=-1) return dp[site][sum][p][k];
    int len=f?num[site]:9;
    node ans,cur;
    ans.cnt=0;
    for(int i=0; i<=len; i++)
    {
        if(zero && i==0) cur=dfs(site-1,sum,p,f&&i==len,1);
        else
        {
            if(p==0) cur=dfs(site-1,sum+i,p^1,f&&i==len,0);
            else cur=dfs(site-1,sum-i,p^1,f&&i==len,0);
        }
        ll tep=(i*ten[site])%mod;
        ans.cnt=(ans.cnt+cur.cnt)%mod;
        ans.sum=(ans.sum+cur.sum+cur.cnt*tep)%mod;
    }
    if(!f && !zero) dp[site][sum][p][k]=ans;
    return ans;
}
ll solve(ll x)
{
    if(x<0) return 0;
    int cnt=0;
    while(x)
    {
        num[++cnt]=x%10;
        x/=10;
    }
    node ans=dfs(cnt,200,0,1,1);
    return ans.sum;
}
int main()
{
    ten[1]=1;
    for(int i=2; i<=20; i++) ten[i]=(ten[i-1]*10)%mod;
    while(scanf("%lld%lld%d",&l,&r,&k)!=-1)
    {
        printf("%lld\n",((solve(r)-solve(l-1))%mod+mod)%mod);
    }
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值