【HDU】3555【Bomb】

题目链接

此题题意就是给你T个n,找出n以内的包含49的数的个数。
很裸的一题数位dp。
直接dp包含49的数的个数有点麻烦,所以我先算出不包含49的数的个数,然后用n+1来减(因为计算不包含49的数中是包括0的,所以减了之后还要加1)。
在搜索的过程中记录三个数,l表示当前是第几位,mach表示上一位是否为4,upp表示之前的位数是否都是取最大值,如果之前的数都是取最大值,当前的位只能取0到n的当前位,而不是0到9.
然后开始搜索,出现连续的49就跳过。
dp[j][i]记录第j位时上一位是否为4(i表示)不包含49的数的个数,用记忆化,如果搜过就直接加上。
因为上一位是否为4决定了当前位能否为9,对后面数的个数有影响,所以要加一维i。
上代码

#include<bits/stdc++.h>
using namespace std;
int t;
long long n;
int l,a[109];
long long dp[109][3];
long long dfs(int l,bool mach,bool upp) {
    if(l<=0) return 1;
    if(upp==0 && dp[l][mach]!=-1) return dp[l][mach];
    int up;
    if(upp==1) up=a[l];
    else up=9;
    long long sum=0;
    for(int j=0; j<=up; j++) {
        if(mach==1 && j==9) continue;
        sum+=dfs(l-1,j==4,upp==1 && j==up);
    }
    if(upp==0) dp[l][mach]=sum;
    return sum;
}
long long ans(long long x) {
    while(x>0) {
        l++;
        a[l]=x%10;
        x/=10;
    }
    return dfs(l,0,1);
}
int main() {
    scanf("%d",&t);
    memset(dp,-1,sizeof(dp));
    while(t--) {
        scanf("%lld",&n);
        l=0;
        printf("%lld\n",n+1-ans(n));
    }
    return 0;
}

转载于:https://www.cnblogs.com/linjiale/p/9872742.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值