世界真的很大
又是一道原来做过的题
集中一天研究了数位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
*/
嗯,就是这样

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

被折叠的 条评论
为什么被折叠?



