浏览器标题切换
浏览器标题切换end

寒假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
复制代码

 

posted @   抓水母的派大星  阅读(119)  评论(0编辑  收藏  举报
编辑推荐:
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」
点击右上角即可分享
微信分享提示