ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

P1590 失踪的7【洛谷算法习题】

P1590 失踪的7【洛谷算法习题】 P1590 失踪的7网页链接P1590 失踪的7题目描述远古的 Pascal 人也使用阿拉伯数字来进行计数但是他们又不喜欢使用7 77因为他们认为7 77是一个不吉祥的数字所以 Pascal 数字8 88其实表示的是自然数中的7 7718 1818表示的是自然数中的16 1616。请计算在正整数n nn范围以内包含有多少个 Pascal 数字。输入格式第一行为正整数t tt接下来t tt行每行一个正整数n nn且保证输入的n nn是 Pascal 数字输出格式对于每个正整数n nn输出n nn以内的 Pascal 数的个数。输入输出样例 #1输入 #12 10 20输出 #19 18说明/提示对于所有数据1 ≤ t ≤ 10000 1 \leq t \leq 100001≤t≤100001 ≤ n ≤ 2 32 − 1 1 \leq n \leq 2^{32}-11≤n≤232−1。解题思路本题要求统计从1 11到给定正整数n nn中不含数字7 77的数的个数。由于n nn最大可达2 32 − 1 2^{32}-1232−1且询问次数较多采用数位 DP高效统计[ 0 , n ] [0, n][0,n]内不含7 77的整数个数最后减去0 00即可。1. 问题等价转化所谓 Pascal 数字就是十进制表示中不含数字7 77的正整数。给定一个 Pascal 数字n nn要求1 ∼ n 1 \sim n1∼n中 Pascal 数字的数量等价于求[ 0 , n ] [0, n][0,n]中不含7 77的整数个数再减去1 11去掉数字0 00。因此核心是计算≤ n \le n≤n且数位中不出现7 77的非负整数个数。2. 数位 DP 设计状态定义dfs(pos, lim)表示当前处理到从高位数的第pos位lim标记前几位是否达到上界。返回在后续低位任意填且不出现7 77的方案数。转移枚举当前位可填数字0 ∼ u p 0\sim up0∼up若lim为真up为当前位上限否则为9 99。若枚举数字为7 77则跳过否则累加递归结果。记忆化当lim false时当前状态只与pos有关可以用数组f[pos]记录避免重复计算。分解数位将x xx的十进制各位存入数组d从高位到低位调用dfs(len-1, true)。3. 算法步骤初始化记忆化数组f为− 1 -1−1。对每个询问n nn将n nn拆分为十进制数位。计算res dfs(最高位, true)得到[ 0 , n ] [0, n][0,n]中不含7 77的整数个数。输出res - 1即[ 1 , n ] [1, n][1,n]中的 Pascal 数字个数。4. 复杂度分析时间复杂度数位 DP 状态数O ( 位数 × 2 ) O(\text{位数} \times 2)O(位数×2)每个状态枚举0 ∼ 9 0\sim 90∼9总复杂度O ( 10 ⋅ L ) O(10 \cdot L)O(10⋅L)其中L ≤ 10 L \le 10L≤102 32 − 1 2^{32}-1232−1最多十位。t ≤ 10 4 t \le 10^4t≤104总运算量极小。空间复杂度O ( L ) O(L)O(L)存储数位数组和记忆化数组。总结利用数位 DP 记忆化搜索逐位枚举并跳过数字7 77快速计算[ 0 , n ] [0, n][0,n]中不含7 77的整数数量。最后减去0 00即得答案。该方法能高效处理多组大范围询问。代码简要说明calc(x)将x xx拆位后调用dfs返回[ 0 , x ] [0, x][0,x]中不含7 77的整数个数。dfs(pos, lim)递归统计当前状态下的合法数字个数lim限制当前位是否达到上限非限制状态下使用记忆化f[pos]优化。主函数读入每个n nn输出calc(n) - 1。代码内容#includebits/stdc.husingnamespacestd;#defineendl\ntypedeflonglongll;typedefunsignedlonglongull;typedefvectorvectorllvvt;typedefpairll,llpll;constll N1e310;constll INF1e18;constll M1e610;constll mod1e97;ll d[1100],len;ll f[1100];lldfs(ll pos,boollim){if(pos-1)return1;if(!limf[pos]!-1)returnf[pos];ll uplim?d[pos]:9;ll ret0;for(ll i0;iup;i){if(i7)continue;retdfs(pos-1,limid[pos]);}if(!lim)f[pos]ret;returnret;}llcalc(ll x){len0;while(x){d[len]x%10;x/10;}returndfs(len-1,true);}intmain(){ios::sync_with_stdio(0);cin.tie(0),cout.tie(0);memset(f,-1,sizeof(f));ll T;scanf(%lld,T);while(T--){ll x;scanf(%lld,x);printf(%lld\n,calc(x)-1);}return0;}
返回列表