HDU 3652 浅谈数位动态规划朝花夕拾Ver2.0

本文介绍了一种使用数位动态规划(DP)的方法,解决求小于n且是13的倍数并包含数字'13'的数的数量的问题。通过详细解释算法思路及代码实现过程,帮助读者理解如何利用数位DP解决复杂计数问题。

这里写图片描述
世界真的很大
又是一道原来做过的题
集中一天研究了数位DP之后回头来做一做这道题
和这道题有点像: HDU 3555

看题先:

description:

求小于n是13的倍数且含有'13'的数的个数

input:

多组数据,每组数据一个整数n

output:

每组数据一个整数表示答案

和之前那道49的题类似,但是由于还要求了mod 13是0
所以不能单单考虑反面没有13,还需要有13且mod不为0,mod为0且不含13,不含13且mod不为0,这样一来反而麻烦
不如老老实实的去按照正面来dfs
首先考虑dfs是需要的参数,pos是肯定的,lim也是同理
由于被13整除,所以还要带一个余数val
然后还要考虑之前的数位有没有出现13,再来一个bool变量have
又由于13是两位数,所以有没有13和上一位出现的数是什么有关,就保存了一个上一位的变量pre

考虑上一位的数只有是1才是有可能使得这一位出现13,所以其实我们只需要知道上一位是不是1就行了,这样pre就退化成了一个bool参数

而have反正也是bool参数,所以干脆一起表示了
have为0表示之前没有出现过13且上一位不是1
have为1表示之前没有出现13且上一位是1
have为2表示之前出现了13

因为之前只要有13,前一位是什么都没有意义了,所以可以这样表示

完整代码:

#include<stdio.h>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
typedef long long dnt;

dnt f[20][5][20],b;
int a[100];

dnt dfs(int pos,int have,int val,int lim)
{
    dnt ans=0;
    if(pos==-1) return have==2 && val==0;
    if(!lim && f[pos][have][val]!=-1) return f[pos][have][val];
    int up=lim ? a[pos] : 9;
    for(int i=0;i<=up;i++)
    {
        int p=have;
        if(have==0&&i==1) p=1;
        else if(have==1&&i==3) p=2;
        else if(have==1&&i!=1) p=0;
        ans+=dfs(pos-1,p,(val*10+i)%13,lim && i==up);
    }
    if(!lim) f[pos][have][val]=ans;
    return ans;
}

dnt solve(dnt n)
{
    int cnt=0;
    while(n)
    {
        a[cnt++]=n%10;
        n/=10;
    }
    return dfs(cnt-1,0,0,1);
}

int main()
{
    memset(f,-1,sizeof(f));
    while(scanf("%lld",&b)!=EOF)
        cout << solve(b) <<endl;
    return 0;
}
/*
EL PSY CONGROO
*/

嗯,就是这样

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值