[HDU 4507] 吉哥系列故事――恨7不成妻
求所有满足要求的数的平方和
不只是统计个数,而是与每个数得具体取值有关
维护三个值
dp[dep][sum][num].num表示长度为dep的前面的数模7的余数为sum,前面几位数字之和模7为num的满足要求的数的个数
dp[dep][sum][num].sum表示长度为dep的前面的数模7的余数为sum,前面几位数字之和模7为num的满足要求的数的和
dp[dep][sum][num].sq表示长度为dep的前面的数模7的余数为sum,前面几位数字之和模7为num的满足要求的数的平方和
设当前位位i,则有如下转移
tmp=dfs(dep-1,(sum*10+i)%7,(num+i)%7,flag&&(i==lim))
ans.sq+=tmp.num*(i*mi_10[dep-1])^2+2*(i*mi_10[dep-1])*tmp.sum+tmp.sq
ans.sum+=tmp.num*(i*mi_10[dep-1])+tmp.sum
ans.num+=tmp.num
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 #define mod 1000000007 5 struct node{ ll sq,sum,num; }dp[20][20][10]; 6 int dig[20]; 7 ll mi_10[20]; 8 ll sq(ll x){ return x*x%mod; } 9 node dfs(int dep,int sum,int num,int flag){ 10 if(!dep)return (node){0,0,sum&&num}; 11 if(!flag&&dp[dep][sum][num].num!=-1)return dp[dep][sum][num]; 12 int lim=flag?dig[dep]:9; 13 node ans={0,0,0}; 14 for(int i=0;i<=lim;i++){ 15 if(i==7)continue; 16 node tmp=dfs(dep-1,(sum*10+i)%7,(num+i)%7,flag&&(i==lim)); 17 ll cur=i*mi_10[dep-1]%mod; 18 ans.sq=(ans.sq+((tmp.num*sq(cur)%mod+2*cur%mod*tmp.sum%mod)%mod+tmp.sq)%mod)%mod; 19 ans.sum=(ans.sum+(tmp.num*cur%mod+tmp.sum)%mod)%mod; 20 ans.num=(ans.num+tmp.num)%mod; 21 } 22 if(!flag)dp[dep][sum][num]=ans; 23 return ans; 24 } 25 ll solve(ll x){ 26 int dd=0; 27 while(x)dig[++dd]=x%10,x/=10; 28 return dfs(dd,0,0,1).sq; 29 } 30 int main(){ 31 int T; 32 scanf("%d",&T); 33 memset(dp,-1,sizeof(dp)); 34 mi_10[0]=1LL; 35 for(int i=1;i<20;i++) 36 mi_10[i]=mi_10[i-1]*10%mod; 37 while(T--){ 38 ll A,B; 39 scanf("%lld%lld",&A,&B); 40 printf("%lld\n",((solve(B)-solve(A-1))%mod+mod)%mod); 41 } 42 return 0; 43 }