LightOJ 1140 How Many Zeroes
题意:写出一个给定区间的每个数,求出一共写了多少个零。
解法:数位DP,定义dp[len][flag][num]:len的定义为数位的长度,flag定义为前导0和没有前导0的两种状态,num定义为写的满足条件的0的个数。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdlib> 5 #include<cmath> 6 #include<algorithm> 7 #define inf 0x7fffffff 8 #define exp 1e-10 9 #define PI 3.141592654 10 using namespace std; 11 typedef long long LL; 12 LL digit[21]; 13 LL dp[21][2][21]; 14 LL dfs(LL len,bool flag,LL p,LL p2,bool fp) 15 { 16 if (!len) 17 { 18 if (!flag) 19 return p2-p; 20 else return 0; 21 } 22 if (!fp && dp[len][flag][p2-p]!=-1) return dp[len][flag][p2-p]; 23 LL ret=0; 24 LL fpmax= fp ? digit[len] : 9 ; 25 for (LL i=0 ;i<=fpmax ;i++) 26 { 27 bool ok= i==0 ? true : false; 28 LL temp; 29 if (i==0) temp=1 ; else temp=0 ; 30 ret += dfs(len-1,flag&&ok,flag?p+temp:p ,p2+temp,fp&&i==fpmax); 31 } 32 if (!fp) return dp[len][flag][p2-p]=ret; 33 return ret; 34 } 35 LL f(LL n) 36 { 37 if (n==-1) return -1; 38 if (n==0) return 0; 39 LL len=0; 40 while (n) 41 { 42 digit[++len]=n%10; 43 n /= 10; 44 } 45 return dfs(len,true,0,0,true); 46 } 47 int main() 48 { 49 int t; 50 int ncase=1; 51 cin>>t; 52 while (t--) 53 { 54 LL a,b; 55 scanf("%lld%lld",&a,&b); 56 memset(dp,-1,sizeof(dp)); 57 printf("Case %d: %lld\n",ncase++,f(b)-f(a-1)); 58 } 59 return 0; 60 }