bzoj 1026: [SCOI2009]windy数【数位dp】

忘记limit不能记WA了一发……
典型数位dp,变成work(r)-work(l-1),然后dfs的时候记录w当前位置,la上一个数选的什么,lm当前位是否有上限,ok当前位是否可以不考虑差大于等于2的情况(前面全是0)
然后对于lm和ok都为0的情况记忆化一下即可
啊bzoj不知道为啥给cmath下的abs判CE……换成algorithm就没事

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=15;
long long l,r,f[N][N],a[N],tot;
long long dfs(int w,int la,int lm,int ok)
{
	if(!lm&&!ok&&f[w][la])
		return f[w][la];
	if(!w)
		return 1;
	long long r=0;
	if(lm)
	{
		for(int i=0;i<=a[w];i++)
			if(abs(la-i)>1||ok)
				r+=dfs(w-1,i,i==a[w],ok&&i==0);
	}
	else
	{
		for(int i=0;i<=9;i++)
			if(abs(la-i)>1||ok)
				r+=dfs(w-1,i,0,ok&&i==0);
	}
	if(!lm&&!ok)
		return f[w][la]=r;
	else
		return r;
}
long long wk(long long x)
{
	tot=0;
	while(x)
		a[++tot]=x%10,x/=10;
	return dfs(tot,13,1,1);
}
int main()
{
	scanf("%lld%lld",&l,&r);
	printf("%lld\n",wk(r)-wk(l-1));
	return 0;
}
posted @ 2018-08-01 22:51  lokiii  阅读(155)  评论(0编辑  收藏  举报