不要62 HDU - 2089 (数位dp解法)

本文介绍了一种使用数位动态规划(DP)解决特定数字限制问题的方法,通过实例讲解如何避免状态冲突,确保在给定区间内找到满足特定条件的数字数量。条件包括数字的每一位不能出现4,且连续两位不可为62。

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

题意:

题目链接:https://vjudge.net/problem/HDU-2089

给你一个区间[ l, r ],让你输出在该区间中满足以下两个条件的数有多少个,条件一:数字的每一位不能出现4,条件二:数字的连续两位不可以是 62 。

解题思路:

由于这个题目的数据比较弱,预处理下直接输出。假设这个题目的范围变成 : (1 <= l <= R <= 1e18) 就不可以暴力了。这时候数位dp就会展示其强大之处。

具体参照代码,类似就是个模板了。写这个题解就是记录个模板,方便以后查看、理解、复习。主要谈了下limit。

AC代码:

#include<bits/stdc++.h>
#define up(i, x, y) for(ll i = x; i <= y; i++)
#define down(i, x, y) for(ll i = x; i >= y; i--)
#define bug prllf("*********\n")
#define debug(x) cout<<#x"=["<<x<<"]" <<endl
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
typedef long long ll;
typedef unsigned long long ull;
const double eps = 1e-8;
const ll mod = 1e9 + 7;
const ll maxn = 1e5 + 7;
const double pi = acos(-1);
const ll inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3fLL;
using namespace std;

ll a[20], dp[20][2], l, r;
//ll ans = 0;

ll dfs(ll pos, ll pre, ll statue, ll limit) // status 为 0 代表当前位的前一位是 6 反之不是6
{
//    ans ++ ;
    if(pos == 0) return 1;
    if(!limit && dp[pos][statue] != -1) return dp[pos][statue];
    /**********************************************************************
    // 有限制是不可以记录状态的,因为此时的状态和无限制时候的状态不一致
    // 比如: 假设限制是 不可以连续出现两个 1 ,如: 11 12211 211 这些
    // 数字都是不合法的求 1 - 521 有多少合法的数字: dp[ pos ][ pre ] 代表
    // 当前位置是pos,前一位置的数是 pre ,的合法状态。假设百位现在枚举到 0 ,
    // 现在limit == 0,是无限制的, 然后十位枚举到2,个位枚举到 1,会产生
    // 一个状态dp[1][2],并且容易计算出dp[1][2] = 10(因为位置为 1 的(个位数)前一个数字是2,
    // 所以10个数字 0 - 9 都合法),这个状态会被记录下来,继续dfs,一直到百位是5,十位是2时候,
    // 此刻就会递归到了pos = 1,pre = 2 的这一层,然而dp[ 1 ][ 2 ]的状态是10,
    // 如果不判断limit,程序直接返回状态dp[ 1 ][ 2 ],显然是不对的,因为现在百位和十位都在上限了,
    // 所以当前pos == 1的位置只能取 [ 0、1 ]这两个数字不会产生 9 个合法的数,
    // 这时候就产生了状态冲突问题,所以当limit有限制的时候不理他,直接算,因为这样的状态并不多。
    *******************************************************************************/

    ll top = limit ? a[pos] : 9;  // 设置当前位置可以枚举的上界
    ll num = 0;

    for(int i = 0; i <= top; i++)
    {
        if(pre == 6 && i == 2) continue;
        if(i == 4) continue;
        num += dfs(pos - 1, i, i == 6, limit && i == a[pos]);
    }

    if(!limit) dp[pos][statue] = num; // 有限制是不可以记录状态的
    return num;
}

ll solve(ll x)
{
    memset(dp, -1, sizeof(dp));
    ll len = 0;
    while(x)  // 取出每一位的上限
    {
        a[++len] = x % 10;
        x /= 10;
    }
    return dfs(len, -1, 0, 1);
}

int main()
{
    while(~scanf("%lld %lld", &l, &r))
    {
//        ans = 0;
        if(l == r && 0 == l) break;
        printf("%lld\n", solve(r) - solve(l - 1));
//        debug(ans);// 1 - 1e18 才需要计算 320次
    }
}

 

### HDU OJ 2089 Problem Solution and Description The problem titled "不高兴的津津" (Unhappy Jinjin) involves simulating a scenario where one needs to calculate the number of days an individual named Jinjin feels unhappy based on certain conditions related to her daily activities. #### Problem Statement Given a series of integers representing different aspects of Jinjin's day, such as homework completion status, weather condition, etc., determine how many days she was not happy during a given period. Each integer corresponds to whether specific events occurred which could affect her mood positively or negatively[^1]. #### Input Format Input consists of multiple sets; each set starts with two positive integers n and m separated by spaces, indicating the total number of days considered and types of influencing factors respectively. Following lines contain details about these influences over those days until all cases are processed when both numbers become zero simultaneously. #### Output Requirement For every dataset provided, output should be formatted according to sample outputs shown below: ```plaintext Case k: The maximum times of appearance is x, the color is c. ``` Where `k` represents case index starting from 1, while `x` stands for frequency count and `c` denotes associated attribute like colors mentioned earlier but adapted accordingly here depending upon context i.e., reasons causing unhappiness instead[^2]. #### Sample Code Implementation Below demonstrates a simple approach using Python language to solve this particular challenge efficiently without unnecessary complexity: ```python def main(): import sys input = sys.stdin.read().strip() datasets = input.split('\n\n') results = [] for idx, ds in enumerate(datasets[:-1], start=1): data = list(map(int, ds.strip().split())) n, m = data[:2] if n == 0 and m == 0: break counts = {} for _ in range(m): factor_counts = dict(zip(data[2::2], data[3::2])) for key, value in factor_counts.items(): try: counts[key] += value except KeyError: counts[key] = value max_key = max(counts, key=lambda k:counts[k]) result_line = f'Case {idx}: The maximum times of appearance is {counts[max_key]}, the reason is {max_key}.' results.append(result_line) print("\n".join(results)) if __name__ == '__main__': main() ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值