C - B-number(数位dp)

看不懂我写的哪个字了,哪句话了,哪段代码了,欢迎提出来啦,大家一起学习一起进步啦
欢迎交流

A wqb-number, or B-number for short, is a non-negative integer whose decimal form contains the sub- string “13” and can be divided by 13. For example, 130 and 2613 are wqb-numbers, but 143 and 2639 are not. Your task is to calculate how many wqb-numbers from 1 to n for a given integer n.
Input
Process till EOF. In each line, there is one positive integer n(1 <= n <= 1000000000).
Output
Print each answer in a single line.
Sample Input
13
100
200
1000
Sample Output
1
1
2
2
题意:
给你一个数,找这个数中含有13,13必须是连着的数,再一个这个数可以被13整除,给你的数比较大,用数位dp
我觉得要弄懂数位dp关键是要把dfs中的递归弄明白,在大脑中模拟一遍过程,先是
从最高位开始,for循环为0,表示最高位取0,然后进入下层dfs,此时是第二位,for循环为0。。。。。。我感觉好好想想这个地方比较有好处

#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include<stdio.h>
#include<string.h> 
#include<limits.h>
#include<stdbool.h>
#include<vector>
#include<queue>
#include<map>
#define maxn  1505
using namespace std;
typedef __int64 ll;
int w[50];
ll dp[25][15][3];//dp[i][j][k]表示第i位余数是j,状态是k,关于状态(0表示普通状态,1表示前一位是1,2表示含有13
ll dfs(int pos,int st,bool limit,int mod)
{
	if(pos==-1)
	{
		return st==2&&mod==0 ;//**只有既含有13,最后的余数等于0,才能返回1**
	}
	if(!limit&&dp[pos][mod][st]!=-1)
	{
		return dp[pos][mod][st];//记忆化
	}
	
	int up=limit?w[pos]:9;
	ll ret=0;
	for(int i=0;i<=up;i++)//代表的是这一位可以放的数
	{
		int tmp=(mod*10+i)%13;//余数,下面有详细的解释
		 if(st==2)
		{
		ret+=dfs(pos-1,2,limit&&w[pos]==i,tmp);
		}
		else if(st==1&&i==3)
		{
		ret+=dfs(pos-1,2,limit&&w[pos]==i,tmp);
		}
		else if(i==1)
		{
		ret+=dfs(pos-1,1,limit&&w[pos]==i,tmp);
		}
		
		else{
			ret+=dfs(pos-1,0,limit&&w[pos]==i,tmp);
		}
	 } 
	 if(!limit)
	 {
	 	dp[pos][mod][st]=ret;
	 }
	 return ret;
}
ll solve(ll n)
{
	int len=0;
	while(n)
	{
	w[len++]=n%10;//分解获得每一位
	n=n/10;	
	}
	return dfs(len-1,0,1,0);
}
int main()
{
	ll n;
	memset(dp,-1,sizeof(dp));//之所以初始化为-1是因为前面判断这个dp之前算没算过,上面代码用的着
	while(scanf("%lld",&n)!=EOF)
	{
	
		printf("%lld\n",solve(n)); 
	}
	return 0;
}

int tmp=(mod*10+i)%13;//余数
看下图解释
在这里插入图片描述
大家如果有什么疑问欢迎提出来啦,很希望与各位大佬交流,有错误也尽管提出来了,我会尽快回复的啦

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值