洛谷 P4999(数位DP)

六眼飞鱼酱① 提交于 2020-03-26 19:31:43

###洛谷 P4999 题目链接 ###

 

题目大意:给你一个区间,求这段区间中所有数的,数位上的,数字之和。

 

分析:

这题与 洛谷 P2602 相似,稍微改一下就可以了。

求出 0 ~ 9 的个数,然后分别乘以 0 ~ 9 ,取模相加即可。要注意的是,在统计之和时,需要 加 mod 以保正答案正确,不然会 WA 两个点。

 

代码如下:

 

#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
typedef long long ll;
const ll p = (ll) (1e9+7);
ll n,m;
int a[20],t;
ll dp[20][20];
ll dfs(int pos,int t,int sum,bool lead,bool limit){
    if(pos==0) return sum%p;
    if(!limit&&!lead&&dp[pos][sum]!=-1) return dp[pos][sum]%p;
    int up=limit?a[pos]:9;
    ll res=0;
    for(int i=0;i<=up;i++){
        if(lead&&i==0) res=(res%p+dfs(pos-1,t,sum,true,limit&&i==a[pos])%p)%p;
        else res=(res%p+dfs(pos-1,t,i==t?(sum+1):sum,false,limit&&i==a[pos])%p)%p;
    }
    if(!limit&&!lead) dp[pos][sum]=res%p;
    return res%p;
}
ll solve(ll x,int t)
{
    int pos=0;
    while(x){
        a[++pos]=x%10;
        x/=10;
    }
    return dfs(pos,t,0,true,true);
}
int main()
{
    //freopen("test.in","r",stdin);
    //freopen("test.out","w",stdout);
    memset(dp,-1,sizeof(dp));
    scanf("%d",&t);
    while(t--){
    scanf("%lld%lld",&n,&m);
    ll ans=0;
    for(int i=0;i<=9;i++){
        ll res=(solve(m,i)%p-solve(n-1,i)%p)%p;
        ans=(ans%p+(res%p*i)%p+p)%p;
     }
     printf("%lld\n",ans );
 }
}

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!