码迷,mamicode.com
首页 > 其他好文 > 详细

HDU 4507 有点复杂却不难的数位DP

时间:2014-10-02 03:55:32      阅读:269      评论:0      收藏:0      [点我收藏+]

标签:style   blog   color   io   os   for   sp   div   c   

首先来说,,这题我wrong了好几次,代码力太弱啊。。很多细节没考虑。。

题意:给定两个数 L R,1 <= L <= R <= 10^18 ;求L 到 R 间 与 7 无关的数的平方和

什么数与7 无关?

1 没有数字7

2 不是7的倍数

3 所有数字的和不是7的倍数

 

我们先来考虑一下  如果这题问的是: L 到 R 间 与7 无关的数有多少个?  

这道题该怎么思考? 给一点提示  dp 方程可以写成三维的 num(i,j,k) 其中 i 代表数的位数 j 代表 这个数对7取模的余数 k 代表这个数所有数字和对7取模的值,至于num(i,j,k) 当让就是这种数的个数了, 方程的转化也很简单  从数末尾逐步填数字 l (0~9)的话 num(i+1,(j*10+l)%7,(k+l)%7)+=num(i,j,k);

 接下来 我默认你知道 num[i][j][k] 该怎么求了 这个时候 再来考虑一下 L 到 R 间与7 无关的数的和 ? 这个时候不用考虑的太复杂,,因为首先,你在求num[i][j][k]的时候已经求出了所有的满足条件的数的所有可能,要求和,无非就是哪一位的那个数字有多少个。

如果我们的dp是逐步往数的末尾填数 ,这个时候可以这样写 sum(i,j,k)其中i,j,k和num的i,j,k一个意思,然后sum表示满足这种情况的数的和 方程的转换可以写为:同样从数末尾逐步填数字 l (0~9)-- num(i+1,(j*10+l)%7,(k+l)%7)+=sum(i,j,k)*10+num(i,j,k)*l;

 

再来考虑平方和就比较容易了,,我们知道如果前面的数是a 我们往后面塞一个数字l 那么我们要求的数的平方和是---(10*a+l)^2 也就是100*a*a+20*a*l+l*l

方程我就不写了,,然后接下来的思路都是和上面的类似

贴出渣渣的代码。。。

  1 #include<iostream>
  2 #include<stdio.h>
  3 #include<string.h>
  4 #include <string>
  5 #include <cmath>
  6 #include <algorithm>
  7 #include <map>
  8 #include <set>
  9 #include <queue>
 10 #include <stack>
 11 #include<stdlib.h>
 12 #include <vector>
 13 using namespace std;
 14 #pragma comment(linker, "/STACK:1024000000,1024000000")
 15 #define ll __int64
 16 #define CL(a,b) memset(a,b,sizeof(a))
 17 #define MAXNODE 100010
 18 ll MOD=1000000007;
 19 
 20 ll s,e;
 21 
 22 ll dp[30][7][7];
 23 ll wsu[30][7][7];
 24 ll num[30][7][7];
 25 ll val[30];
 26 void initval()
 27 {
 28     int i=0;
 29     val[1]=1;
 30     val[0]=0;
 31     for(i=2;i<=19;i++)
 32     {
 33         val[i]=val[i-1]*10;
 34     }
 35 }
 36 
 37 void initdp()
 38 {
 39     int i,j,k,l;
 40     CL(dp,0);
 41     CL(num,0);
 42     CL(wsu,0);
 43     for(i=0;i<10;i++)
 44     {
 45         if(i==7)continue;
 46         dp[1][i%7][i%7]+=i*i;
 47         wsu[1][i%7][i%7]+=i;
 48         num[1][i%7][i%7]++;
 49     }
 50     num[0][0][0]=1;
 51     for(i=1;i<29;i++)
 52     {
 53         for(j=0;j<7;j++)
 54         {
 55             for(k=0;k<7;k++)
 56             {
 57                 for(l=0;l<10;l++)
 58                 {
 59                     if(l==7)continue;
 60                     num[i+1][(j+l)%7][(k*10+l)%7]+=num[i][j][k]%MOD;
 61                     num[i+1][(j+l)%7][(k*10+l)%7]%=MOD;
 62                     wsu[i+1][(j+l)%7][(k*10+l)%7]+=(wsu[i][j][k]*(ll)10+(ll)l*(num[i][j][k]))%MOD;
 63                     wsu[i+1][(j+l)%7][(k*10+l)%7]%=MOD;
 64                     dp[i+1][(j+l)%7][(k*10+l)%7]+=(((ll)l*(ll)l*num[i][j][k])+dp[i][j][k]*100+(ll)2*(ll)l*wsu[i][j][k]*(ll)10)%MOD;
 65                     dp[i+1][(j+l)%7][(k*10+l)%7]%=MOD;
 66                 }
 67  //               printf("%d %d %d %I64d\n",i,j,k,dp[i][j][k]);
 68             }
 69         }
 70     }
 71 }
 72 
 73 ll pro(ll n)
 74 {
 75     if(n==0)return 0;
 76     ll rem=0;
 77     ll nu[30];
 78     int w,i,j,k;
 79     nu[0]=0;
 80     ll tem=n,va;w=1,rem=0;
 81     while(tem!=0)
 82     {
 83         nu[w]=tem%10;
 84         tem/=10;
 85         w++;
 86     }
 87     va=0;
 88     int su=0;
 89     ll v=0;
 90     while(--w)
 91     {
 92         if(nu[w]==7)
 93         {
 94             for(i=1;i<w;i++)nu[i]=9;
 95             nu[w]=6;
 96         }
 97         for(i=nu[w]-1;i>=0;i--)
 98         {
 99             if(i==7)continue;
100             for(j=0;j<7;j++)
101             {
102                 for(k=0;k<7;k++)
103                 {
104                     if((su+i+j)%7==0)continue;
105                     if(((ll)v+(ll)i*val[w]+(ll)k)%7==0)continue;
106                     ll pre=(va+(ll)i*(val[w]%MOD))%MOD;
107                     pre%=MOD;
108                     rem+=(((pre*pre)%MOD)*(num[w-1][j][k]%MOD))%MOD;
109                     rem%=MOD;
110                     rem+=dp[w-1][j][k]%MOD;;
111                     rem%=MOD;
112                     rem+=((((ll)2*pre)%MOD)*wsu[w-1][j][k]%MOD)%MOD;
113                     rem%=MOD;
114                 }
115             }
116         }
117         rem%=MOD;
118         va+=(nu[w]*(val[w]%MOD))%MOD;
119         va%=MOD;
120         v+=nu[w]*(val[w]%7);
121         v%=7;
122         su+=nu[w];
123         su%=7;
124     }
125     if(v!=0&&su!=0)rem+=(va*va)%MOD;
126     return rem%MOD;
127 }
128 
129 int main()
130 {
131     int tt;
132     initval();
133     initdp();
134     scanf("%d",&tt);
135     while(tt--)
136     {
137         scanf("%I64d %I64d",&s,&e);
138         ll rs=pro(s-1LL);
139         ll re=pro(e);
140         ll rem=re-rs;
141         rem=rem%MOD;
142         if(rem<0)rem+=MOD;
143  //       printf("%I64d %I64d ",rs,re);
144         printf("%I64d\n",rem);
145     }
146     return 0;
147 }

 

HDU 4507 有点复杂却不难的数位DP

标签:style   blog   color   io   os   for   sp   div   c   

原文地址:http://www.cnblogs.com/loloveping/p/4003787.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!