定义
表示当前已经填了
个数字,并且非
数字为
时的总方案数。显然
的大小不会超过
,最多
个非零数字,所以
不会超过
求区间
的上等数字,等价于求区间
的个数减去
的个数
核心代码:
当
时说明数字已经枚举完,显然是一个升等数字,所以返回
。
这里的
是数位
,记录当前的状态,
一开始初始化为
,采用记忆化搜索:如果当前
并且
,则说明后面的状态已经搜索过了,现在直接使用即可
int dfs(int pos, int cnt, int state){
if(pos == -1) return 1;
if(state && dp[pos][cnt] != -1) return dp[pos][cnt];
int up = (state ? 9 : p[pos]);
int ans = 0;
for(int i = 0; i <= up; i ++){
if(cnt + (i != 0) >= 4) break;
ans += dfs(pos - 1, cnt + (i != 0), state || (i < up));
}
if(state) dp[pos][cnt] = ans;
return ans;
}
总代码:
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define int long long
#define IOS ios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
#define HelloWorld IOS;
const int N = 25;
int dp[N][5], p[N];
int dfs(int pos, int cnt, int state){
if(pos == -1) return 1;
if(state && dp[pos][cnt] != -1) return dp[pos][cnt];
int up = (state ? 9 : p[pos]);
int ans = 0;
for(int i = 0; i <= up; i ++){
if(cnt + (i != 0) >= 4) break;
ans += dfs(pos - 1, cnt + (i != 0), state || (i < up));
}
if(state) dp[pos][cnt] = ans;
return ans;
}
int work(int x){
int pos = 0;
while(x){
p[pos ++] = x % 10;
x /= 10;
}
return dfs(pos - 1, 0, 0);
}
void solve(){
memset(dp, -1, sizeof(dp));
int l, r; cin >> l >> r;
cout << work(r) - work(l - 1) << endl;
return ;
}
signed main(){
HelloWorld;
int tt = 1;
cin >> tt;
while(tt --) solve();
return 0;
}



京公网安备 11010502036488号