HDU-4507 吉哥系列故事――恨7不成妻 (数位dp)

来源:互联网 发布:c语言三个数排序 编辑:程序博客网 时间:2024/05/17 17:55

J - 吉哥系列故事――恨7不成妻

 HDU - 4507 
题解:数位dp
和简单的数位dp不同,这道题要算所有合法数的平方和


考虑到一个数可以写成X=ΣAi*Pi,(其中Ai为X每一位的值,Pi=10^i)
因为(A+B)^2=A*A+2*A*B+B*B
(X1+X2+X3+...+Xn)^2=X1^2+2*X1*(X2+X3+...+Xn)+(X2+X3+...+Xn)^2
=X1^2+2*X1*(X2+X3+...+Xn)+X2^2+2*X2*(X3+...+Xn)+(X3+...+Xn)^2
...
一直递归分治,即可求的


因此在dp时,只要记录当前状态合法数的数量cnt,当前状态之后的和sum,平方和sqr

A=Ai*Pi

now.cnt=now.cnt+nxt.cnt;

now.sum=now.sum+nxt.sum+A*nxt.cnt;
now.sqr=now.sqr+A*A*nxt.cnt+2*A*nxt.sum+nxt.sqrt;


#include<iostream>#include<cstdio>#include<algorithm>#include<string.h>using namespace std;typedef long long LL;const LL mod = 1e9 + 7;int len,a[20];LL p[20];struct node{    LL cnt,sqr,sum;    bool vis;    node(LL a=0,LL b=0,LL c=0,bool d=0){cnt=a;sqr=b;sum=c;vis=d;}}dp[20][10][10];node dfs(int i,LL mod1,LL mod2,bool mark){    if(i==0){        if(mod1%7==0||mod2%7==0) return node(0);        return node(1);    }    if(dp[i][mod1][mod2].vis&&mark==0) return dp[i][mod1][mod2];    int mx=mark?a[i]:9;    node ret;    for(int j=0;j<=mx;j++){        if(j==7) continue;        node tmp=dfs(i-1,(mod1+j)%7,(mod2*10+j)%7,mark&&j==mx);        LL A=j*p[i-1]%mod;        ret.cnt=(ret.cnt+tmp.cnt)%mod;        ret.sum=(ret.sum+A*tmp.cnt%mod+tmp.sum)%mod;        ret.sqr=(A*A%mod*tmp.cnt%mod+2*A*tmp.sum%mod+tmp.sqr+ret.sqr)%mod;    }    if(mark==0) {        dp[i][mod1][mod2]=ret;        dp[i][mod1][mod2].vis=1;    }    return ret;}LL solve(LL x){    len=0;    while(x) a[++len]=x%10,x/=10;    node ret=dfs(len,0,0,1);    return ret.sqr%mod;}int main(){    int T;    LL l,r;    p[0]=1;    for(int i=1;i<=18;i++) p[i]=p[i-1]*10;    cin>>T;    for(int cas=1;cas<=T;cas++){        cin>>l>>r;        cout<<(solve(r)-solve(l-1)+mod)%mod<<endl;    }    return 0;}


0 0
原创粉丝点击