[SCOI2009] windy数
题目大意:求([L,R])中相邻每一位之差至少大于(2)的数字个数,(只有一位也算)
Solution
数位(dp)直接搞,对于前导零,其实不用卡下界,只要一个用一个状态来表示就好,还可以取(0)
Code
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cstdlib>
#define pf(x) printf("%d
", x);
int dp[15][15];
int a[15];
int dfs(int pos, int last, bool uflag, bool dflag){
if(pos < 0 && last >= 0) return 1;
else if(pos <0) return 0;//全是0
if(!uflag && !dflag && dp[pos][last] != -1) return dp[pos][last];//不用卡上下界,是一个完全状态
int up = uflag ? a[pos] : 9;//取上界
int tmp = 0;//不用取下界,因为可以为0
for(int i = 0; i <= up; ++i){
if(abs(i - last) >= 2 || last == -233){
if(i == 0 && dflag)//依然为0
tmp += dfs(pos - 1, -233, uflag && (i == up), (i == 0) && dflag );
else //随便了
tmp += dfs(pos - 1, i, uflag && (i == up), 0);
}
}
if(!uflag && !dflag) dp[pos][last] = tmp;//完全状态
return tmp;
}
inline int cal(int x){
int cnt = -1;
memset(a, 0, sizeof(a));
while(x){
a[++cnt] = x % 10;
x /= 10;
}
int qwq = dfs(cnt, -233, 1, 1);
return qwq;
}
int main(){
int l, r;
scanf("%d %d", &l, &r);
memset(dp, -1, sizeof(dp));//0
printf("%d", cal(r) - cal(l - 1));
return 0;
}