zoukankan      html  css  js  c++  java
  • hdu4507(数位DP)

    题目意思: 给定一个区间,求这段区间中,不含7,对7取余为0,各个位数相加之和对7取余为0的数的平方和。

    设d[i][j][k][m]代表长度为i的,对7取余为j的,各个位数相加之和对7取余为k的数的平方和,

    但是算平方和需要用到这些数的和,这些数的个数。所以用了一个结构体数组保存每种状态的Count,sum1,.sum2;

    (ago+k1)^2+(ago+k2)^2+(ago+k3)^2=3*ago^2+2*ago*(k1+k2+k3)+k2^2+k2^2+k3^2;

    =Count1*ago^2+2*ago*sum1+sum2;

    需要注意取模运算和long long

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define LL long long
    #define MOD 1000000007
    #define maxn 20
    using namespace std;
    const int N=20;
    LL  md[N];
    LL  digit[maxn];
    LL ans=0;
    struct node
    {
       LL Count=0,sum1=0,sum2=0;
    };
    node dp[maxn][7][7][2];
    int visit[maxn][7][7][2];
    node  dfs(int len,int pre,int before, int state,bool fp) //dfs版本的纯属暴力枚举每一个数字,而递推版本的是考虑了前缀的影响
    {
        if(state)
             {
                 node temp;
                 temp.Count=0;
                 temp.sum1=0;
                 temp.sum2=0;
                 return temp;
             }
        if(len==0 && (pre==0 || before==0))
            {
                 node  temp;
                 temp.Count=0;
                 temp.sum1=0;
                 temp.sum2=0;
                 return temp;
            }
        else if(len==0)
            {
                  node  temp;
                 temp.Count=1;
                 temp.sum1=0;
                 temp.sum2=0;
                 return temp;
            }
        if(!fp && visit[len][pre][before][state]== 1) //
        {
             return dp[len][pre][before][state];
        }
        node  ret ;
        int  fpmax = fp ? digit[len] : 9 ;
        for(int i=0;i<=fpmax;i++) //分别算出以i开头的数的方案数,
        {
            node next=dfs(len-1,(((pre*10+i))%7) ,(before+i)%7,i==7 | state,fp && i == fpmax);
            //temp=temp%MOD;
            //ret+=(temp*temp)%MOD;
            LL  ago   = ( i*md[len-1] )%MOD;
            ret.Count = (ret.Count +  next.Count) %MOD;
            ret.sum1  = (ret.sum1  + ( ago*next.Count ) %MOD + next.sum1) %MOD;
            ret.sum2  = ( ret.sum2 + (next.Count* ( (ago*ago )%MOD ) ) %MOD +(2*ago*next.sum1)%MOD + next.sum2 ) %MOD;
        }
        if(!fp)
        {
            dp[len][pre][before][state]= ret;
            visit[len][pre][before][state]=1;
        }
        return  ret;
    }
    
    LL f(LL n)
    {
        int len=0;
        while(n)
        {
            digit[++len] = n % 10;
            n /= 10;
        }
        LL ans=0;
        ans+=dfs(len,0,0,0,true).sum2;
         return ans;
    }
    void init()
    {
        memset(visit,0,sizeof(visit));
    }
    int main()
    {
       // freopen("test.txt","r",stdin);
        int t;
        scanf("%d",&t);
        md[0]=1;
        for(int i=1;i<=N;i++)
            md[i]=(md[i-1]*10)%MOD;
        while(t--)
        {
            init();
            LL n,m;
            scanf("%I64d%I64d",&n,&m);
             LL ans1=f(m);
             LL ans2=f(n-1);
           printf("%I64d
    ", (ans1-ans2 + MOD)%MOD );
        }
        return 0;
    }
  • 相关阅读:
    springCloud学习6(Spring Cloud Sleuth 分布式跟踪)
    springCloud学习5(Spring-Cloud-Stream事件驱动)
    springCloud学习4(Zuul服务路由)
    springCloud学习3(Netflix Hystrix弹性客户端)
    springCloud学习笔记2(服务发现)
    EFCore
    webBrowser.DocumentText重新赋值无效解决方法
    C# SQLite写入和读取DateTime类型
    自定义协议链接 ------2.实践篇
    自定义协议链接 ------1.原理篇
  • 原文地址:https://www.cnblogs.com/xianbin7/p/4749032.html
Copyright © 2011-2022 走看看