P2657 [SCOI2009] windy 数

题目链接Miku

数论dp的典型例题

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
int dp[1001][15];

//事实上,对于此dp还有个限制
//没有任何限制条件 
int l[1001];
int c;
int p;
int p2;

long long dfs(int pos,int pre,int leadz,int li){
	//当前位置,前一位置,有无前道零,有无限制 
	int ret=0;
	if(pos>p2)
	return 1;
	if(dp[pos][pre]!=-1&&leadz==0&&li==0){
		return dp[pos][pre];
	}
	int lim=li?  l[p2-pos+1] :9;
	//能枚举到那个数由限制决定 
	for(int i=0;i<=lim;++i){
		if(i==0&&leadz) ret+=dfs(pos+1,i,1,i==lim&&li);
		else
		if(i&&leadz) ret+=dfs(pos+1,i,0,i==lim&&li);
		else
		if(abs(pre-i)>=2)
		ret+=dfs(pos+1,i,0,i==lim&&li);
	}
	if(leadz==0&&li==0)
	dp[pos][pre]=ret;
	return ret;
}
long long solve(int p){
	p2=0;
	while(p>0){
		l[++p2]=p%10;
		p/=10; 
	}
	memset(dp,-1,sizeof(dp));
	return dfs(1,0,1,1);
}
int main(){
	cin>>p>>c;
	cout<<solve(c)-solve(p-1);
	return 0;
} 
posted @ 2020-08-28 21:50  Simex  阅读(69)  评论(0编辑  收藏  举报