首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

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

2013-03-27 
HDU 4507 吉哥系列故事——恨7不成妻(数位DP)转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode

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

转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents    by---cxlove

Tencent马拉松初赛第二场的鬼畜题。。。其实还是比较裸的数位DP。给出的三种定义,都可以用位DP解决。而且是比较基础的。至于平方和,大概是这样的。我们假设dfs进下一层的数字是x,那么当前长度是len的话,最高位添加的数字是i那么我们令f=i*10^(len-1),那么f+x便是当前的数。如果是平方的话,然后将其展开f^2+x^2+2*f+x。其实sigma(x^2)大概就是整个题目要求维护的结果,sigma(f^2)也是可以求的,那么还需要sigma(2*f*x),也就是sigma(x)。可以看出我们需要维护三个东西,与7有关的数有多少个,sigma(与7有关的数),sigma(与7有关的数的平方)。剩下的都没什么问题了,求整个的平方和,然后减去与7有关的数的平方和,就是结果。大概注意下各个地方不要溢出就行了。
#include<cstdio>#include<cstring>#include<algorithm>#include<vector>#include<cmath>#include<iostream>#define LL long long#define MOD 1000000007#define mp(a,b) make_pair(a,b)using namespace std;//长度,是否有7,数字和%7,数字%7LL s1[20][2][7][7],s2[20][2][7][7],cnt[20][2][7][7];int bit[20],len;LL fac[20]={1};pair<pair<int,int>,int> dfs(int len,int a,int b,int c,int limit){    if(cnt[len][a][b][c]!=-1&&!limit) return mp(mp(cnt[len][a][b][c],s1[len][a][b][c]),s2[len][a][b][c]);    if(!len){        if(!a&&b&&c) cnt[len][a][b][c]=0LL;        else cnt[len][a][b][c]=1LL;        s1[len][a][b][c]=s2[len][a][b][c]=0LL;        return mp(mp(cnt[len][a][b][c],s1[len][a][b][c]),s2[len][a][b][c]);    }    int up=limit?bit[len]:9;    LL tcnt=0LL,ts1=0LL,ts2=0LL;    for(int i=0;i<=up;i++){        int nl=len-1,na=(a||i==7),nb=(b+i)%7,nc=(c*10+i)%7;        LL f=(fac[len-1]*i)%MOD;        pair<pair<int,int>,int> pre=dfs(nl,na,nb,nc,limit&&(i==up));        ts1=(ts1+pre.first.second+pre.first.first*f)%MOD;        ts2=(ts2+pre.second+(f*f%MOD)*pre.first.first+2*f*pre.first.second)%MOD;        tcnt=(tcnt+pre.first.first)%MOD;    }      if(!limit){        cnt[len][a][b][c]=tcnt;        s1[len][a][b][c]=ts1;        s2[len][a][b][c]=ts2;    }    return mp(mp(tcnt,ts1),ts2);}LL sum(LL n){    LL a=n,b=n+1,c=2*n+1;    int x=3,y=2;    if(a%x==0) a/=x,x=1;if(a%y==0) a/=y,y=1;      if(b%x==0) b/=x,x=1;if(b%y==0) b/=y,y=1;    if(c%x==0) c/=x,x=1;if(c%y==0) c/=y,y=1;    a%=MOD;b%=MOD;c%=MOD;    return (a*b%MOD)*c%MOD;}LL slove(LL n){    len=0;    LL m=n;    while(n){        bit[++len]=n%10;        n/=10;    }    return (sum(m)-dfs(len,0,0,0,1).second)%MOD;}int main(){    for(int i=1;i<20;i++)        fac[i]=(fac[i-1]*10)%MOD;    int t;    LL l,r;    memset(cnt,-1,sizeof(cnt));    scanf("%d",&t);    while(t--){        scanf("%I64d%I64d",&l,&r);        //cout<<slove(r)<<" "<<slove(l-1)<<endl;        printf("%I64d\n",((slove(r)-slove(l-1))%MOD+MOD)%MOD);    }    return 0;}


热点排行