HDOJ 4507 吉哥系列故事——恨7不成妻(数位DP)

来源:互联网 发布:许小年水平怎么样知乎 编辑:程序博客网 时间:2024/05/17 04:13
题意: 在一定区间内和7无关的数字的平方和。
如果一个整数符合下面3个条件之一,那么我们就说这个整数和7有关——
1、整数中某一位是7;
2、整数的每一位加起来的和是7的整数倍;
3、这个整数是7的整数倍;


对于第一个条件:在DP中多开一维0/1表示前面的位数中是否出现1
对于第二个条件:在DP中多开一维表示前面位数的和对7取余
对于第三个条件:在DP中多开一维表示生成的这个数对7取余

那么考虑一下边界:
如果出现7并且两个取余都是0,那么这个数就是跟7相关。
然后再来维护一下平方和。
这里用一个sum来维护,具体公式就不推了很好推的。
还要维护个数和平方和,那么就开一个结构体来DP;
在进行维护数据时要注意公式的正确性和取模。

#include<stdio.h>#include<algorithm>#include<string>#include<string.h>#include<queue>#include<vector>#include<stack>#include<math.h>#include<map>#include<set>#include<iostream>using namespace std;#define INF 0x7f7f7f7f#define LL long longconst LL mod=1e9+7;struct node{    LL cnt;    LL sum;    LL sum2;}dp[20][2][10][10];int a[20];LL l,r;LL q(int x){    LL tmp=1;    for(int i=1;i<=x;i++)    {        tmp*=10;        tmp%=mod;    }    return tmp;}node dfs(int pos,int pre,int sta,int sa,int sb,bool limit){    if(pos==-1)    {        node tmp;        if(sta==1||sa%7==0||sb%7==0)        {            tmp.cnt=0;            tmp.sum=0;            tmp.sum2=0;            return tmp;        }        else        {            tmp.cnt=1;            tmp.sum=0;            tmp.sum2=0;            return tmp;        }    }    if(!limit&&dp[pos][sta][sa][sb].cnt!=-1)        return dp[pos][sta][sa][sb];    int up=limit ? a[pos] : 9;    node tmp;    tmp.cnt=tmp.sum=tmp.sum2=0;    for(int i=0;i<=up;i++)    {        node ttp=dfs(pos-1,i,sta||i==7,(sa+i)%7,(sb*10+i)%7,limit&&i==a[pos]);        if(ttp.cnt>=1)        {            LL x=i*q(pos);            x%=mod;            tmp.cnt+=ttp.cnt;            tmp.cnt%=mod;            if(pos==0)                tmp.sum+=i;            else                tmp.sum+=ttp.sum+x*ttp.cnt%mod;            tmp.sum%=mod;            tmp.sum2+=(((x*x)%mod)*ttp.cnt)%mod+((2*x)%mod)*ttp.sum%mod+ttp.sum2%mod;            tmp.sum2%=mod;        }    }    if(!limit)        dp[pos][sta][sa][sb]=tmp;    return tmp;}node solve(LL x){    int pos=0;    while(x)    {        a[pos++]=x%10;        x/=10;    }    return dfs(pos-1,-1,0,0,0,true);}int main(){    int t;    for(int i=0;i<20;i++)        for(int j=0;j<2;j++)            for(int k=0;k<10;k++)                for(int kk=0;kk<10;kk++)                    dp[i][j][k][kk].cnt=-1;    scanf("%d",&t);    while(t--)    {        scanf("%I64d%I64d",&l,&r);        LL ans=(solve(r).sum2-solve(l-1).sum2);        if(ans<0)            ans+=mod;        printf("%I64d\n",ans);    }return 0;}


0 0
原创粉丝点击