• 寒假Day20:数位dp


    数位dp:在数位上做动态规划

    Bomb

     HDU - 3555 

    求含49的数字个数(49连号)。

    #include<stdio.h>
    #include<iostream>
    #include<string.h>
    #include<algorithm>
    #include<queue>
    #include<cmath>
    using namespace std;
    #define inf 0x3f3f3f3f
    typedef long long ll;
    //找0-n含49的数字个数(49看作一个整体)
    ll dp[50][2];//不含49的数字的个数
    //[数位] 当数为i时,有多少个数不含49
    
    int digit[20];//2^63-1//19位
    
    ll dfs(int len,bool if4,bool limit)//执行的是数位dp(dfs+记忆化搜索)
    {
        if(len==0)
            return 1;
        if(limit==0&&dp[len][if4])//并且当前的数位已经统计过
            return dp[len][if4];
        ll sum=0,up;
        if(limit==1)
            up=digit[len];
        else
            up=9;
        for(int i=0;i<=up;i++)
        {
            if(if4&&i==9)//不要49 
                continue;
               //没有49所有数的数量
            sum+=dfs(len-1,i==4,limit&&i==up);
        }
        if(!limit)//是一个完整的状态,等到下一次dfs的时候可以直接返回
            dp[len][if4]=sum;
        return sum;
    }
    
    ll solve(ll x)
    {
        int num=0;//有多少个数位
        while(x)
        {
            digit[++num]=x%10;
            x/=10;
        }
        dfs(num,0,1);//从高位,从上面往下面遍历
    }
    
    int main()
    {
        int t;
        cin>>t;
        while(t--)
        {
            ll n;
            cin>>n;
            cout<<n+1-solve(n)<<endl;//+1因为算上0再减去不含49的
            // 给了上下界cout<<solve(m)-solve(n-1)<<endl;
        }
        return 0;
    }

    不要62

     HDU - 2089 

     给出a、b两个区间,求所有不含有4或62(62连号)的数字的个数。

    AC代码:

     1 #include<string.h>
     2 #include<iostream>
     3 #include<stdio.h>
     4 #include<algorithm>
     5 #include<queue>
     6 #include<vector>
     7 #include<map>
     8 #include<cmath>
     9 using namespace std;
    10 #define inf 0x3f3f3f3f
    11 const int N=50;
    12 typedef long long ll;
    13 
    14 int digit[25];
    15 ll dp[N][2];
    16 
    17 ll dfs(int len,bool if6,bool limit)
    18 {
    19     if(len==0)
    20         return 1;
    21     if(limit==0&&dp[len][if6])
    22         return dp[len][if6];
    23     ll cnt=0,up;
    24     if(limit==1)
    25         up=digit[len];
    26     else
    27         up=9;
    28     for(int i=0; i<=up; i++)
    29     {
    30         if(if6&&i==2)//不要62
    31             continue;
    32         if(i==4)//不要4
    33             continue;
    34         cnt+=dfs(len-1,i==6,limit&&i==up);
    35     }
    36     if(limit==0)
    37         dp[len][if6]=cnt;
    38     return cnt;
    39 }
    40 
    41 ll solve(ll x)
    42 {
    43     int num=0;
    44     while(x)
    45     {
    46         digit[++num]=x%10;
    47         x/=10;
    48     }
    49     return dfs(num,0,1);
    50 }
    51 
    52 int main()
    53 {
    54     ll n,m;
    55     while(cin>>n>>m)
    56     {
    57         if(n==0&&m==0)
    58             break;
    59         memset(dp,0,sizeof(dp));
    60         cout<<solve(m)-solve(n-1)<<endl;
    61     }
    62     return 0;
    63 }
    View Code
  • 相关阅读:
    [XJOI]noip43 T2多人背包
    Codeforces Round #198 (Div. 2)E题解
    [XJOI]noip40 T2统计方案
    Codeforces Round #198 (Div. 2)C,D题解
    Codeforces Round #198 (Div. 2)A,B题解
    9.19[XJOI] NOIP训练37
    9.18[XJOI] NOIP训练36
    kmp算法详解
    [模板系列] AC自动姬
    luogu1967[NOIP2013D1T3] 货车运输 (最大生成树+LCA)
  • 原文地址:https://www.cnblogs.com/OFSHK/p/12262117.html
Copyright © 2020-2023  润新知