P2657 [SCOI2009] windy 数
//URL:https://www.luogu.com.cn/problem/P2657 /* 数位dp 1.若前面有小于目标位数字的 后面可以任意选 2.直接用记忆化搜索 3.若有前导零 后一位任意 4.若未搜完 done==1 就是还要搜 只有done===0才可以return f[pos][sta]:在pos位 前一位是sta的 总和 1.若是没有限制的done==0 f[pos][pre-sta]=sum(f[pos-1][<=pre-sta-2]) 2.反之done==1 就要一步步搜 pos==0 return 1 */ /* 25 50 20 1 10 9 */ #include<cstdio> #include<iostream> #include<algorithm> #include<cmath> #include<string.h> #include<queue> #include<vector> #include<bits/stdc++.h> typedef long long ll; #define ddd printf("-----------------------\n"); using namespace std; const int maxn=1e1 +10; const int mod=998244353; const int inf=0x3f3f3f3f; int f[30][12],a[30]; int dfs(int pos,int sta,int done) { if(pos==0) return 1; if(done==0&&f[pos][sta]!=-1) return f[pos][sta]; int res=0; int end=done? a[pos]:9; for(int i=0;i<=end;i++) { if(abs(i-sta)<2) continue; if(i==0&&sta==11) res+=dfs(pos-1,11,done&&i==end); else res+=dfs(pos-1,i,done&&i==end); } if(done==0) f[pos][sta]=res; return res; } int solve(int x) { memset(f,-1,sizeof(f)); //memset(a,0,sizeof(a)); a[0]=0; while(x) { a[++a[0]]=x%10; x/=10; } return dfs(a[0],11,1); } int main() { ios::sync_with_stdio(false); int a,b;cin>>a>>b; cout<<solve(b)-solve(a-1)<<'\n'; return 0; }