【数位DP】HDU4507[吉哥系列故事——恨7不成妻]题解

来源:互联网 发布:sql where in 编辑:程序博客网 时间:2024/05/21 23:00

题目概述

[L,R] 中同时满足[1.不存在 7 。2.不是 7 的倍数。3.每位加起来不是 7 的倍数。]的数的平方和

解题报告

恩……又是数位DP水……水个头啊,平方和是什么鬼???

这道题要用平方和公式 (a+b)2=a2+2ab+b2 来统计答案,对于每个状态,记录三个量: num 表示该状态的方案数, sum 表示该状态所有方案的数的总和, sqr 表示该状态所有方案的数的平方的总和。

然后将一个数 x 看做每位相加,比如:

12=1×101+2×100122=(10+2)2=102+2×10×2+22

这样就可以方便的转移了。详细一点?不如膜拜ChesterKing!

发现记忆化真的好写……感觉又重学了一遍数位DP……

示例程序

#include<cstdio>using namespace std;typedef long long LL;const int maxn=19,MOD=1e9+7;int te,a[maxn+5];LL L,R,p[maxn+5];inline void AMOD(LL &x,LL tem) {if ((x+=tem)>=MOD) x-=MOD;}#define Mod(x) ((x)%MOD)struct data{    LL num,sum,sqr;data(LL A=-1,LL B=-1,LL C=-1) {num=A;sum=B;sqr=C;}    void Add(const data &c,int i,int x)    {        AMOD(num,c.num);AMOD(sum,Mod(c.sum+Mod(p[x]*c.num)*i));        AMOD(sqr,Mod(c.sqr+Mod(p[x]*c.sum)*i*2+Mod(Mod(Mod(p[x]*i)*Mod(p[x]*i))*c.num)));    }};data f[maxn+5][7][7];void Make() {p[0]=1;for (int i=1;i<=maxn;i++) p[i]=Mod(p[i-1]*10);}data Dfs(int i,int A,int M,bool fl){    if (!i) return data(A&&M,0,0);if (!fl&&~f[i][A][M].sqr) return f[i][A][M];    int MAX=9;if (fl) MAX=a[i];data ans=data(0,0,0);    for (int j=0;j<=MAX;j++) if (j!=7)        ans.Add(Dfs(i-1,(A+j)%7,((M<<3)+(M<<1)+j)%7,fl&&j==MAX),j,i-1);    if (!fl) f[i][A][M]=ans;return ans;}inline int Solve(LL n){    a[0]=0;do a[++a[0]]=n%10,n/=10; while (n);    return Dfs(a[0],0,0,true).sqr;}int main(){    freopen("program.in","r",stdin);    freopen("program.out","w",stdout);    for (Make(),scanf("%d",&te);te;te--) scanf("%lld%lld",&L,&R),printf("%d\n",Mod(Solve(R)+MOD-Solve(L-1)));    return 0;}
阅读全文
0 0