http://www.lightoj.com/volume_showproblem.php?problem=1140
题意:一个人依次写下从m到n的数,问你会写下几个‘0’
普通的按位DP,预处理一个数组记录长度为i的数中首位为j时共有几个0
统计的时候写晕了,竟然忘记了某个数本身的0带来的影响,上次做过一个类似的题目,询问的是二进制位数上的0 和 1,这次是十进制,差不多的
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
long long dp[35][10];
void init(){
memset(dp,0,sizeof(dp));
for(int i=1;i<=26;i++){
for(int j=0;j<=9;j++)
for(int k=0;k<=9;k++)
dp[i][j]+=dp[i-1][k];
dp[i][0]+=(long long)pow(10.0,i-1);
}
}
long long calc(long long num){
int a[20],tot=0;
long long tmp=num;
while(tmp){
a[tot++]=tmp%10;
tmp/=10;
}
long long ans=0;
int cnt=0;
if(tot==1) return 1;
ans=1;
for(int i=1;i<tot;i++)
{
for(int j=1;j<=9;j++)
ans+=dp[i][j];
}
for(int i=tot-1;i>=0;i--)
{
if(i==tot-1)
{
for(int j=1;j<a[i];j++)
{
ans+=dp[i+1][j];
}
}
else
{
for(int j=0;j<a[i];j++)
{
ans+=dp[i+1][j];
ans+=(long long)cnt*(long long )pow(10.0,i);
}
}
if(a[i]==0) cnt++;
}
ans+=cnt;
return ans;
}
int main()
{
init();
long long m,n;
int t,ca=1;
scanf("%d",&t);
while(t--)
{
scanf("%lld%lld",&m,&n);
printf("Case %d: ",ca++);
if(m==0) printf("%lld\n",calc(n));
else
{
long long a=calc(n),b=calc(m-1);
printf("%lld\n",a-b);
}
}
return 0;
}