一般的数位dp都是输出方案数,但这道题求平方和。

所以要用一个结构体保存dfs到这一层的信息:有多少个数满足条件cnt,满足条件的数的和是多少,它们的平方和是多少(一般求平方和都要维护和)

注意:记忆化搜索时要判断lim,如果有lim,就不能记录,因为记录了下一次就会被直接返回,而有限制的位就没有被搜索到

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll mod=1e9+7;
int num[20];
ll pow10[22];
struct node {
    ll cnt,power,sum;
    node() { cnt=-1; power=0; sum=0; }
    node(ll cnt,ll power,ll sum) : cnt(cnt),power(power),sum(sum) { }
}dp[20][200][10];
node dfs(int pos,int sum,int mod1,int lim)
{
    if(pos==1){
        if((sum%7==0)||(!mod1)) return node(0,0,0);
        return node(1,0,0);
    }
    if(!lim&&dp[pos][sum][mod1].cnt!=-1) return dp[pos][sum][mod1];
    int up=lim?num[pos-1]:9; //printf("up:%d\n",up);
    node rt=node(0,0,0);
    for(int i=0;i<=up;i++){
        if(i==7) continue;
        int nx_lim=(lim&&i==up),nx_mod=(mod1*10+i)%7;
        //这一位的贡献=这一位的最高位i*对应的10的次方再加上下一位
        
        node nx=dfs(pos-1,sum+i,nx_mod,nx_lim);
        rt.cnt=(rt.cnt+nx.cnt)%mod;
        rt.sum=(rt.sum+(nx.sum + i * pow10[pos-1] %mod * nx.cnt %mod) %mod )%mod;
        //nx.power是已经算出来后面的一堆数的平方和 现在那一堆数应该加上这一位的贡献再平方 
        //x^2+y^2  x是nx.power y是i*pow10[pos-1] 这里的pos其实是向后推了一位的 
        rt.power=(rt.power + nx.power + i * i %mod * pow10[pos-1] %mod * pow10[pos-1] %mod *nx.cnt %mod) %mod;
        //+2*x*y
        rt.power=(rt.power+ 2 * i * pow10[pos-1] %mod * nx.sum %mod) %mod;
    }
    if(!lim) dp[pos][sum][mod1]=rt;
    return rt;
}
ll solve(ll x)
{
    int cnt=0;
    while(x){
        num[++cnt]=x%10; x/=10;
    }
    node rt=dfs(cnt+1,0,0,1);//cnt+1!!
    //因为dfs中的终止条件是pos==1 所以这里应该是cnt+1 
    return rt.power %mod;
}
int main()
{
    freopen("seven.in","r",stdin);
    freopen("seven.out","w",stdout);
    int T; ll l,r;
    pow10[1]=1;
    for(int i=2;i<=20;i++) pow10[i]=pow10[i-1]*10%mod;
    scanf("%d",&T);
    while(T--){
        scanf("%lld%lld",&l,&r);
        
        ll ans=solve(r)-solve(l-1);
        ans=(ans+mod)%mod;
        printf("%lld\n",ans);
    }
}
/*
3
1 9
10 11
17 17
*/

 

posted on 2019-07-18 17:22  rua-rua-rua  阅读(189)  评论(0编辑  收藏  举报