X - 1024 HDU - 5898 -数位DP

本文介绍了一种使用数位动态规划(数位DP)的方法,来解决在一个给定区间内寻找特定模式的数字个数问题。具体来说,目标是在连续的奇数个数为偶数,连续的偶数个数为奇数的条件下,找到符合条件的数字数量。文章通过详细的代码解释了如何构建状态转移方程,以及如何利用递归和记忆化搜索来高效求解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • X - 1024

  •  HDU - 5898 
  • 题意:在给定区间内找到符合固定的数字的个数(一段连续的奇数个数为偶数, 一段连续的偶数个数为奇数)
  • 思路:数位dp[数位][到此前面连续的奇数个数][到此前面连续的偶数个数]

  • i为奇数时,1.新开始一段奇数那么前面的偶数个数得是奇数个,2或者延续前面的奇数那么f1不为0,3或者前导0情况
  • i为偶数数,1.新开始一段偶数那么前面的奇数个数得是偶数个,2或者延续前面的偶数那么f2不为0,3.或者前导0情况
  •  
  • #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define maxn 22
    int a[maxn],cas,t;
    ll st,ed,dp[maxn][maxn][maxn];
    ll dfs(int pos,int f1,int f2,bool limit)
    {
        if(pos==0)return (!f1||!(f1&1))&&(!(f2)||(f2&1));
        if(!limit&&dp[pos][f1][f2]!=-1)return dp[pos][f1][f2];
        int up=limit?a[pos]:9;
        ll res=0;
        for(int i=0; i<=up; i++)
        {
            if(!(f1||f2||i))res+=dfs(pos-1,0,0,limit&&i==up);//全部为0
            else if((i&1)&&((f1||f2&1)||(f1==0&&f2==0)))res+=dfs(pos-1,f1+1,0,limit&&i==up);
            //i为奇数时,可以是,1.新开始一段奇数那么前面的偶数个数得是奇数个,2或者延续前面的奇数那么f1不为0,3或者前导0情况
            else if(!(i&1)&&((f2||!(f1&1)||(f1==0&&f2==0))))res+=dfs(pos-1,0,f2+1,limit&&i==up);
            //i为偶数数时,可以是,1.新开始一段偶数那么前面的奇数数个数得是偶数个,2或者延续前面的偶数数那么f2不为0,3.或者前导0情况
        }
        if(!limit)dp[pos][f1][f2]=res;
        return res;
    }
    ll solve(ll x)
    {
        int pos=0;
        while(x)
        {
            a[++pos]=x%10;
            x/=10;
        }
        return dfs(pos,0,0,1);
    }
    int main()
    {
        scanf("%d",&t);
        memset(dp,-1,sizeof(dp));
        while(t--)
        {
            scanf("%lld%lld",&st,&ed);
            printf("Case #%d: %lld\n",++cas,solve(ed)-solve(st-1));
        }
        return 0;
    }
    
  •  
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值