您的位置:首页 > 其它

LightOJ 1140 How Many Zeroes?(数位dp)

2018-02-01 18:45 465 查看


C - How Many Zeroes?

 LightOJ - 1140 

很简单的数位dp,dp[pos][zeronum]来表示位数为pos时0的个数。要注意前导零的问题,当有前导零时,不能把前导零计入个数,所有位数都为0时返回1即可,即数字0。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
int a[20];
long long dp[20][20];
//用iszero来处理前导零问题,当iszero为1时表示有前导零
long long dfs(int pos,int zeronum,int iszero,int limit)
{
if(pos==-1)
{
//到了最低位,有前导零的话返回1
if(iszero)
return 1;
//不然返回0的个数
else
return zeronum;
}
//记忆化搜索,因为要考虑前导零问题,所以需要判断iszero的状态
if(!limit&&dp[pos][zeronum]!=-1&&!iszero)
return dp[pos][zeronum];
int top=limit?a[pos]:9;
long long ans=0;
for(int i=0;i<=top;i++)
{
if(iszero)
//如果之前有前导零,0的个数则为零个,若本位还为0则iszero还是为1
ans+=dfs(pos-1,0,i==0,limit&&i==top);
else
{
if(i==0)
ans+=dfs(pos-1,zeronum+1,0,limit&&i==top);
else
ans+=dfs(pos-1,zeronum,0,limit&&i==top);
}

}
if(!limit&&!iszero)
dp[pos][zeronum]=ans;
return ans;
}

long long solve(long long x)
{
int pos=0;
while(x)
{
a[pos++]=x%10;
x/=10;
}
return dfs(pos-1,0,1,1);
}

int main()
{
int t;
long long l,r;
int kase=0;
scanf("%d",&t);
memset(dp,-1,sizeof(dp));
while(t--)
{
scanf("%lld %lld",&l,&r);
printf("Case %d: %lld\n",++kase,solve(r)-solve(l-1));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  数位dp