• Bomb 【数位dp】


    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? InputThe 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. OutputFor each test case, output an integer indicating the final points of the power.Sample Input3150500Sample Output0115HintFrom 1 to 500, the numbers that include the sub-sequence "49" are "49","149","249","349","449","490","491","492","493","494","495","496","497","498","499",so the answer is 15.

    题意 :在【0,n】范围内有出现了多少次 “49”

    思路:数位dp

    dp[i][0] 表示 长度为 i 不出现 “49” 的个数

    dp[i][1] 表示 长度为 i 最高位为 “9” 且不含“49”的个数

    dp[i][2] 表示 长度为 i 出现 “49” 的个数

     

    那么对0 ~ 2^63-1 内进行初始化

    ll dp[25][3];
    void init(){
        dp[0][0]=1;
        dp[0][1]=dp[0][2]=0;
        for (int i=1;i<=20;i++){
            dp[i][0]=dp[i-1][0]*10-dp[i-1][1];  /* 长度为 i 中 不包含 “49”的个数
    为长度为 i-1 中不含“49”的个数在第 i 位 加 0~9 的个数 减掉 当第 i 位为“4”时,长度为 i-1 
    的数中最高位为“9”的个数 */
            dp[i][1]=dp[i-1][0];/*长度为 i-1的数中不含“49”的数在第 i 位加“9” 
    即为dp[i][1];*/ 
            dp[i][2]=dp[i-1][2]*10+dp[i-1][1];/* 长度为i的数中含“49”的个数等于长度为 i-1 中含“49” 的数字 在第 i 位上放0~9,加当第 i 位为“4”时,长度为 i-1 的数字中,最高位
    为“9”的数字。*/
        }
    
    ll getCnt(ll x){
        ++x; /*为啥加一我也不知道,反正加一就过了 qwq */
        ll ans=len=0;
        while(x){
            num[++len]=x%10;
            x/=10;
        }
        bool fg=false;   /* 种一个标记判断到第i位是 最高位到第i+1位 是否出现“49”*/ 
        num[len+1]=-1;
        for (int i=len;i>=1;i--){
            ans+=dp[i-1][2]*num[i];  //第i位 取(0~num[i]-1)时 长度为i-1的数中含“49”的数 
            if(fg)   ans+=dp[i-1][0]*num[i]; /*如果高位中已经出现过“49”,第i位取(0~num[i]-1)时,长度为i-1中不含“49”的个数*/
            if(!fg && num[i]>4) ans+=dp[i-1][1];  /*当未标记且该位大于4时,取长度为i-1的数中最高位为“9”的数*/
            if(num[i+1]==4 && num[i]==9) fg=1; /*如果该位为9前一位为4 则标记*/
        }
        return ans;
    }
    过题代码如下:
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <functional>
    #include <iostream>
    using namespace std;
    typedef long long ll;
    ll x,len;
    int num[25];
    ll dp[25][3];
    void init(){
        dp[0][0]=1;
        dp[0][1]=dp[0][2]=0;
        for (int i=1;i<=20;i++){
            dp[i][0]=dp[i-1][0]*10-dp[i-1][1];
            dp[i][1]=dp[i-1][0];
            dp[i][2]=dp[i-1][2]*10+dp[i-1][1];
        }
    }
    ll getCnt(ll x){
        ++x;
        ll ans=len=0;
        while(x){
            num[++len]=x%10;
            x/=10;
        }
        bool fg=false;
        num[len+1]=-1;
        for (int i=len;i>=1;i--){
            ans+=dp[i-1][2]*num[i];
            if(fg)   ans+=dp[i-1][0]*num[i];
            if(!fg && num[i]>4) ans+=dp[i-1][1];
            if(num[i+1]==4 && num[i]==9) fg=1;
        }
        return ans;
    }
    int main(){
        init();
        int T;
        scanf("%d",&T);
        while(T--){
            scanf("%I64d",&x);
            printf("%I64d
    ",getCnt(x));
        }
        return 0;
    }
    



  • 相关阅读:
    微信抢红包算法备注
    APP测试-drozer安装和使用
    APP测试--应用签名信息检测
    绕过CDN获得网站真实IP
    UnicodeDecodeError: 'ascii' codec can't decode byte 0xd5 in position 9: ordinal not in range(128)
    检查APP 数据库.xml文件
    APP本地数据库安全
    APP重新打包签名
    APP完整性检测
    dex2jar和jd-gui联合使用查看代码是否经过混淆处理或者加壳
  • 原文地址:https://www.cnblogs.com/acerkoo/p/9490332.html
Copyright © 2020-2023  润新知