zoukankan      html  css  js  c++  java
  • HDU 4507 吉哥系列故事——恨7不成妻(数位DP求平方和)

    一般的数位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
    ",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
    ",ans);
        }
    }
    /*
    3
    1 9
    10 11
    17 17
    */
  • 相关阅读:
    Pycharm创建Django项目示例
    Window下MyCat的下载与安装
    Python中使用xlrd、xlwt、xlutils读写Excel文件
    循环队列(Java实现)
    oracle 创建表
    win10 删除文件卡在99%
    python xx005文件操作
    python xx004集合
    python xx003字典
    不理解
  • 原文地址:https://www.cnblogs.com/mowanying/p/11208695.html
Copyright © 2011-2022 走看看