数位DP统计->Windy数(洛谷2657)
https://www.luogu.com.cn/problem/P2657
题意:给定范围,求windy数个数。windy数是相邻数字差值至少为2的数。
分析:前缀和差分,数位dp,从高到低判。
这里记录前导0的意义在于,如果前面都是0,那么前面的这一位可以看做是-2,在当前的pos位可以选任何数。
如果没有记录前导0,那么前面的数可能存在可能不存在,要按两种情况记录前面的数为-2或者其他。
void solve(){
int l, r;
cin >> l >> r;
vector<int> num;
vector<vector<int>> dp(11, vector<int>(11, -1));
function<int(int, int, bool, bool)> dfs = [&](int pos, int pre, bool lead, bool limit){
if (pos == 0){
return 1;
}
if (!lead && !limit && dp[pos][pre] != -1){
return dp[pos][pre];
}
int up = (limit == true ? num[pos] : 9);
int res = 0;
for (int i = 0; i <= up; ++i){
if (abs(i - pre) >= 2){
res += dfs(pos - 1, (lead && (i == 0)) ? -2 : i, lead && (i == 0), limit && (i == up));
}
}
if (!lead && !limit){
dp[pos][pre] = res;
}
return res;
};
auto cal = [&](int x){
num.resize(1);
while (x){
num.emplace_back(x % 10);
x /= 10;
}
return dfs(int(num.size()) - 1, -2, true, true);
};
cout << cal(r) - cal(l - 1) << '\n';
}

浙公网安备 33010602011771号