《ybtoj高效进阶》第五部分第四章例题1 B数计数

题目大意

求n以内被13整除且含连续字符串13的数个数,多组数据。

思路

f i , j , k f_{i,j,k} fi,j,k为前i位,%13=j,字符串包含情况为k的个数。
k=0:已带有13字符串
k=1:i位为1
k=2:无连续13且第i位不为1。
然后套路。
code:

#include<cstdio>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<cstring>
using namespace std;
int r,f[35][21][21],tot,lyw[35];
inline int dfs(int pos,int x,bool tjh,int wj)
{
	if (!tjh&&f[pos][x][wj]!=-1)
	{
		return f[pos][x][wj];
	}
	if (!pos&&!wj&&!x) return 1;
	if (!pos) return 0;
	int mx=tjh?(r/lyw[pos-1]%10):9;
	int ans=0;
	for (int i=0;i<=mx;i++)
	{
		int res=(x+13-i*lyw[pos-1]%13)%13;
		if (wj==2)
		{
			ans+=dfs(pos-1,res,tjh&&(i==mx),2);//即使当前位为1,依然跑2情况
			if (i==1) ans+=dfs(pos-1,res,tjh&&(i==mx),1);//若为1,也可以被1情况转移(考虑倒着dp)
		}
		if (wj==1)
		{
			if (i==3) ans+=dfs(pos-1,res,tjh&&(i==mx),0)+dfs(pos-1,res,tjh&&(i==mx),1);//只有3时可以转移
		}
		if (wj==0)
		{
			if (i!=1&&i!=3) ans+=dfs(pos-1,res,tjh&&(i==mx),1);//若为1,不能从1情况转移
			if (i!=3) ans+=dfs(pos-1,res,tjh&&(i==mx),0);//若为3,显然无法转移
		}
	}
	if (!tjh) return f[pos][x][wj]=ans;
	else return ans;
}
inline int kyx(int r)
{
	if (r==0) return 0;
	tot=0;
	while (r!=0)
	{
		++tot;
		r/=10;
	}
	int ans=0;
	ans+=dfs(tot,0,1,2);
	return ans;
}
int main()
{
	lyw[0]=1;
	for (int i=1;i<=13;i++) lyw[i]=lyw[i-1]*10;
	memset(f,-1,sizeof(f));
	while (~scanf("%d",&r))
	{
		printf("%d\n",kyx(r));
	}
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值