首页 > 其他分享 >3555.Bomb

3555.Bomb

时间:2024-08-05 20:08:19浏览次数:12  
标签:std 10 3555 Bomb int pos i64 dp

3555.Bomb

题目描述

The counter-terrorists found a time bomb in the dust. But this time the terrorists improve on the time bomb. The number sequence of the time bomb counts from 1 to N. If the current number sequence includes the sub-sequence "49", the power of the blast would add one point.
Now the counter-terrorist knows the number N. They want to know the final points of the power. Can you help them?
大意:求 \(1\) 到 \(N\) 有多少个数字含“49” 。

输入描述

The first line of input consists of an integer T (1 <= T <= 10000), indicating the number of test cases. For each test case, there will be an integer N (1 <= N <= 2^63-1) as the description.

The input terminates by end of file marker.
大意:第一行输入一个\(T\)(\(1\leq T \leq 10000\))表示测试组数,接下来 \(T\) 行每行输入一个 \(N\)(\(1\leq N \leq 2^{63}-1\))表示右边界。

输出描述

For each test case, output an integer indicating the final points of the power.
大意:对于每组测试,输出一个整数表示最后的答案。

解题思路

分析发现数据范围到了long long级别,显然暴力是不可行的,本题是求某一区间内符合某种特征的数字数量,因此可以考虑数位DP,本题也正是一道经典的数位DP入门题,对于数位DP一般有两种做法,一种是像常规DP一样根据转移方程不断推进,另一种则是记忆化搜索,相对而言,记忆化搜索的方法更加套路一些,更容易调试。
先开一个数组digit,用于存放数字(注意要反向存入,便于直接应用最高位的限制条件,同时也可以方便地处理前导零的问题),再开一个dp数组,用于存放中间过程的答案。接下来考虑dfs的传参设置,简单来说要考虑的有三点,当前位置pos,前一个位置pre,当前位置选用的数字是否要受限制(不可以超出范围)。然后对于根据dp数组和dfs参数的状态进行判断选择不同的分支不断递归即可。

代码实现

#include <bits/stdc++.h>

using i64 = long long;

i64 digit[20], dp[20][10];  // 数组大小20是因为10^20 > 2^63-1,dp数组的第二位10则用于和pos的前一个位置比较,一个位置上的数字%10之后不会大于9,因此开10即可。

i64 dfs(int pos, int pre, bool limit) {
    if (pos == 0) {  // 如果已经处理完所有位,则返回1,表示找到一个满足条件的数字。
        return 1;
    }
    if (!limit && dp[pos][pre] != 0) {  // 如果不受限且已经计算过该状态,则直接返回结果,避免重复计算。
        return dp[pos][pre];
    }
    i64 maxn = limit ? digit[pos] : 9, res = 0;  // 如果受限,则最大值为当前位的数值;否则为9。
    for (int i = 0; i <= maxn; i++) {
        if (pre == 4 && i == 9) {  // 如果前一位是4且当前位是9,则跳过这种情况,因为不满足条件。
            continue;
        }
        // 递归处理下一位,注意条件limit && i == digit[pos],limit是当前位数的限制,i == digit[pos]是对下一位的限制,例如520,当前位(百位)是5的时候才需要考虑下一位是不是应该不超过2。
        res += dfs(pos - 1, i, limit && i == digit[pos]);
    }
    if (!limit) {  // 不受限制则使用记忆化
        dp[pos][pre] = res;
    }
    return res;
}

i64 calc(i64 x) {
    int pos = 0;
    while (x > 0) {
        digit[++pos] = x % 10;
        x /= 10;
    }
    return dfs(pos, 0, true);
}

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    std::cout.tie(0);
    int t;
    std::cin >> t;
    while (t--) {
        i64 x;
        std::cin >> x;
        std::cout << x - calc(x) + 1 << "\n";
    }
}

标签:std,10,3555,Bomb,int,pos,i64,dp
From: https://www.cnblogs.com/udiandianis/p/18343794

相关文章

  • F. Bomb
    原题链接题解贪心的每次挑选当前最大的,但是要挑选k次,因此我们没法去遍历挑选的过程,因此我们考虑最终形态,由于每次挑选最大的元素,因此最后所有数一定不超过某个数,二分由此而来code#include<bits/stdc++.h>#definelllonglongusingnamespacestd;lln,k;lla[200005],b[......
  • CSAPP Lab02——Bomb Lab完成思路详解
    看见的看不见的瞬间的永恒的青草长啊大雪飘扬——月亮之上完整代码见:CSAPP/bombatmain·SnowLegend-star/CSAPP(github.com)01字符串比较简单的把输入的字符串和地址“0x402400”内早已存储的字符串相比较。如果两个字符串相等则函数返回,否则炸弹爆炸。这里有......
  • csapp-bomblab(自信满满版)
    反汇编bomb文件要查看机器代码文件的内容,有一类称为反汇编器(disassembler,assembler是汇编程序,dis-加在某些词语前表示相反的意思)的程序非常有用。这些程序根据机器代码产生一种类似于汇编代码的格式。在linux系统中,带‘-d’命令行标志的程序OBJDUMP(表示“objectdump”)可以充当这......
  • CSAPP Lab-2 BOMBLAB
    第二个Lab就比较有趣了。这一个Lab的任务是,我们得到了一个bomb炸弹程序,这个炸弹程序有\(6\)个phase,每个phase都会读取我们的输入,判断我们的输入是否符合要求,如果正确这个phase的炸弹就会被拆除,否则炸弹就会爆炸。我们需要借助各种工具,对程序进行反汇编等等,获得能够......
  • 题解:AT_abc176_e [ABC176E] Bomber
    分析我们可以用\(hf\)和\(wf\)分别储存每行的目标数及每列的目标数。然后我们可以贪心:若想摧毁最多的目标,则选定的位置所在的行是所有行中目标最多的,所在的列是所有列中目标最多的(感性理解一下)。但是,选定的位置也可能有一个目标。在统计摧毁的目标数时,该目标被算了两次......
  • CSAPP Bomb Lab
    frompixiv参考博客手把手教你拆解CSAPP的炸弹实验室BombLabGDB调试-从入门实践到原理Linux上分屏软件Tmux使用教程知识点gdbjump函数名/*地址名jump能够很灵活地在gdb调试汇编代码时跳转当一不小心错过了关键信息时,我们便可以使用jumprun(......
  • Atcoder ABC 333 F - Bomb Game 2
    题目大意(采用0#语言):有n个人,每个人每次要么被“炸掉”,要么就被移到最后面去,概率都是1/2,求最后只剩下初始时排名为第i的人的概率。 这道题跟人数有关,而且跟位置有关。我们定义dp[i]表示一共有i个人,第i个为最后一位留下来时的概率。(不想写公式)定义j从0到i-1,表示从前面i-1......
  • 题解 ABC333F【Bomb Game 2】
    来个可能有点麻烦但不用动脑子的暴力做法。直接设\(f_{i,j}\)表示有\(i\)个人时,第\(j\)个人幸存的概率。显然有\(f_{1,1}=1\)。对于\(i>1\),分类讨论容易得到:\[f_{i,j}=\begin{cases}\frac{f_{i,n}}{2},&j=1\\\frac{f_{i-1,j-1}+f_{i,j-1}}{2},&1<j\lei\\\e......
  • 题解 accoders::NOI 5511【漂亮轰炸(bomb)】
    题解accoders::NOI5511【漂亮轰炸(bomb)】http://47.92.197.167:5283/contest/406/problem/4BZOJ3252是弱化版。problem一棵树,边带权。\(Q\)次询问,给定\(k\)和一个首都点,选择\(k\)条路径轰炸,其中必须由一轮要轰炸首都,但没有要求每条路径都经过首都。每条边只能被炸一次,......
  • CSAPP-Bomb Lab
    这个实验的逻辑是这样的需要使用gdbdebug进入到phase_x的各个函数,但是单步调试step是进不去的(也不难理解,如果gdb可以直接进入那这个实验还有什么难点)但是反汇编得到的结果是全部的内容,通过阅读反汇编代码,找到一些关键节点,通过gdb对二进制进行dubug添加breakpoint从而查看一些......