题解:P2657 [SCOI2009] windy 数
说在前面
update 2025.7.5 发现一处笔误并修改。
注意:本题解不保证存在多项式时间复杂度,如有需要请不要参考此题解。
我也不知道怎么过的……复杂度神奇。
前置芝士:搜索。
题目分析
我们可以想到一个很简单的做法:我们使用 dfs,来搜索可以生成的数。假设现在的最后一位数为
这里我们要注意:如果当前是第一位,则不能为
注意事项
-
当我们发现这个数
\ge l 且\le r 时,我们把答案+1 ,但是不能退出,因为如果直接退出的话我们能可能会漏掉一些位数更多的情况。例如l = 1, r = 200 ,当我们搜索到20 时,如果直接退出的话,我们就会漏掉例如135 。所以不能退出。 -
记得开
long long,如果不开long long,那么当前的数溢出后会变成负数,越来越小,从而导致TLE。
完整代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
int l, r, ans;
void dfs(int x) {
if (x >= l && x <= r) {
ans++;
}
int lst = x % 10;
for (int i = 0; i <= lst - 2; i++) {
if (x * 10 + i > r) break;
dfs(x * 10 + i);
}
for (int i = lst + 2; i <= 9; i++) {
if (x * 10 + i > r) break;
dfs(x * 10 + i);
}
}
signed main() {
cin >> l >> r;
for (int i = 1; i <= 9; i++) {
dfs(i);
}
cout << ans;
return 0;
}
说在后面
能过的原因大概是因为合法的数比较少吧……
特别鸣谢:@woshiSB4 提供的思路与代码。
最后,若代码、思路讲解有误,欢迎提出!