bzoj4521(数位dp

自己的主体思路,没有什么问题,有一个情况没有考虑清楚,但主要还是边界出了问题


失误的情况是:4和8,不能同时出现,但不代表不能出现两个4,这里当时就记了一个参数,当时以为自己想到了一个巧妙的方法(原来是个巧妙的错误。。)

经验——避免这种没有情况的方法就是,1:考场上要对拍 2:注意尝试以一种,怀疑的态度审视自己的思路,再三思考自己认为正确的思路

3:有一个,好的方向就是:尽管wa了好多次,也不放弃自己独特的方法,既然我认为他没有错误,就坚持下去,毕竟创新思维最为重要!!

4:边界!边界!出数据的时候要特别注意边界!!包括各种!!这里是最大边界和最小边界!


就是数位dp的基本做法。

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
using namespace  std;
typedef long long ll;

ll f[20][2][12][2][2][2];
int li[20];

ll dfs(int i,bool same,int last,bool apr,bool a8,bool a4,bool limit)
{
	if (i==0&&apr) return 1;
	if (i==0) return 0;
	
	if (!limit)
	if (f[i][same][last][apr][a8][a4]!=-1) 
 return f[i][same][last][apr][a8][a4];
 	
 	int up=limit? li[i]:9;
 	ll ans=0;
 	
 	for (int j=0;j<=up;j++)
 	{
 		if (j==4&&a8) continue;
 		if (j==8&&a4) continue;
 		
	ans+=dfs(i-1,last==j,j,apr||(same&&last==j),j==8||a8,j==4||a4,limit&&j==up);
	}
	
	if (!limit) f[i][same][last][apr][a8][a4]=ans;
	
	return ans;
}

ll work(ll n)
{
	memset(f,-1,sizeof(f));
	memset(li,0,sizeof(li));
	int tot=0;
	while (n)
	{
		li[++tot]=n%10;
		n=n/10;
	}
	return dfs(tot,false,0,false,false,false,true);
}

int main()
{
	ll l,r;
	scanf("%lld%lld",&l,&r);
	ll ans=work(r);
	if (l==10000000000ll) l++,ans++;
	ans=ans-work(l-1);
	printf("%lld",ans);
	
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值