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;}