【BZOJ】1026 [SCOI2009]windy数 数位dp

110 篇文章 0 订阅
30 篇文章 0 订阅

题目传送门

感觉自己真的是越来越菜了,连数位dp都写不来了……

定义f[i][j]表示当前取到第i位(从高位到低位),当前位置为j的方案数。

然后就是对于是否存在前导0的分类讨论,并同时统计答案。

最后利用差分的思想,把[l,r]的windy数的数量转化成[1,r]的windy数的数量减去[1,l-1]的windy数的数量即可。

附上AC代码:

#include <cstdio>
#include <cctype>
using namespace std;

const int n=9;
int a,b,f[11][11],ans1,ans2,dig[11];

inline char nc(){
	static char ch[100010],*p1=ch,*p2=ch;
	return p1==p2&&(p2=(p1=ch)+fread(ch,1,100010,stdin),p1==p2)?EOF:*p1++;
}

inline void read(int &a){
	static char c=nc();int f=1;
	for (;!isdigit(c);c=nc()) if (c=='-') f=-1;
	for (a=0;isdigit(c);a=a*10+c-'0',c=nc());
	a*=f;return;
}

inline int abs(int a){
	return a>0?a:-a;
}

inline int count(int x){
	if (!x) return 0;
	int len=0,sum=0;
	while (x) dig[++len]=x%10,x/=10;
	for (int i=len; i; --i){
		if (len-i>=2&&abs(dig[i+1]-dig[i+2])<2) break;
		for (int j=0+(i==len); j<dig[i]+(i==1); ++j)
			if (i==len||abs(j-dig[i+1])>=2) sum+=f[i][j];
	}
	for (int i=len-1; i; --i)
		for (int j=1; j<=n; ++j)
			sum+=f[i][j];
	return sum;
}

int main(void){
	read(a),read(b);
	for (int i=0; i<=n; ++i) f[1][i]=1;
	for (int i=2; i<=10; ++i)
		for (int j=0; j<=n; ++j)
			for (int k=0; k<=n; ++k)
				if (abs(j-k)>=2) f[i][j]+=f[i-1][k];
	printf("%d",count(b)-count(a-1));
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值