hdu 4507 数位DP(求和类型)

中文题,题意略,老年人康复练习
数位DP,
和一般的不同,这种数位dp统计数字和或者数字平方和


注意取模!!!


代码:

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
int a[20];
const ll mod=1e9+7;
ll po[20];
struct D{
    ll cnt,sum,sum2;
    D(){}
    D(ll a ,ll b,ll c){cnt=a%mod,sum=b%mod,sum2=c%mod;};
};
D dp[20][10][10];
inline ll add(ll a,ll b){
    return (a+b)%mod;
}
inline ll mul(ll a,ll b){
    return (a*b)%mod;
}
D dfs(int pos,ll sum,ll eve,bool limit){
    if(pos==-1&&eve!=0&&sum!=0) return D(1,0,0);
    if(pos==-1) return D(0,0,0);
    if(!limit  && dp[pos][sum][eve].cnt!=-1) return dp[pos][sum][eve];
    int up=limit?a[pos]:9;
    D ans=D(0,0,0);
    for(ll i=0;i<=up;i++){
        if(i==7) continue;
        D t=dfs(pos-1,(sum*10+i)%7,(eve+i)%7,limit && i==a[pos]);
        ans=D(add(ans.cnt,t.cnt),
              add(ans.sum,add(t.sum,mul(mul(po[pos],i),t.cnt))),
              add(add(add(t.sum2, mul(mul(mul(i, po[pos]),mul(i, po[pos])),t.cnt)), mul(mul(2*i,po[pos]), t.sum)), ans.sum2)
              );
    }
    if(!limit) dp[pos][sum][eve]=ans;
    return ans;
}
D solve(ll x){
    int pos=0;
    while(x){
        a[pos++]=x%10;
        x/=10;
    }
    return dfs(pos-1,0,0,true);
}
int main(){
    memset(dp,-1,sizeof(dp));
    po[0]=1;
    for(int i=1;i<20;i++) po[i]=(po[i-1]*10LL)%mod;
    ll le,ri;
    int t;
    cin>>t;
    while(t--){
        scanf("%lld%lld",&le,&ri);
        printf("%lld
",(solve(ri).sum2-solve(le-1).sum2+mod)%mod);
    }
}




原文地址:https://www.cnblogs.com/zhangxianlong/p/10672516.html