数位DP的第一题(历时7天的惨痛经历。。。)
数位DP通常用f[i][j]或者在加几维,代表长度为i,最高位为j的合法数字的个数
本题 : windy定义了一种windy数。不含前导零且相邻两个数字之差至少为2的正整数被称为windy数。 windy想知道,
在A和B之间,包括A和B,总共有多少个windy数?
先预处理出f数组(见代码)
例 9982
我们先算出 1—8999的所有成立的数
然后定住最高位9
算9000-9899的所有成立的数
继续。。。。
然而 到了9899我们要break
因为之后不会成立了
因为 9900-9982已经都不成立了 99<----
#include<cstdio> #include<iostream> #include<cctype> #include<cstring> using namespace std; #define R register #define IL inline #define II long long II f[20][15]; II base[100]; II a,b; IL void init() { for(R II i=0;i<=9;i++) f[1][i]=1; base[0]=1; for(R II i=1;i<=13;i++) base[i]=base[i-1]*10; for(R II i=2;i<=12;i++) for(R II j=0;j<=9;j++) for(R II k=0;k<=9;k++) { if(j-k>=2||k-j>=2) f[i][j]+=f[i-1][k]; } } IL II calc(R II x) { R II len=1,ans=0; bool fst=true; while(x>=base[len])len++; for(R II i=1;i<len;i++) for(R II j=1;j<=9;j++) ans+=f[i][j]; R II last=0x7fffffff; for(R II i=len;i;i--) { R II tp=x/base[i-1]%10; for(R II j=fst;j<tp;j++) { if(j-last>=2||last-j>=2) ans+=f[i][j]; } if(last-tp<2&&tp-last<2)break; last=tp; fst=0; } return ans; } int main() { ios::sync_with_stdio(false); cin>>a>>b; init(); cout<<(calc(b+1)-calc(a))<<endl; }