2个入门题。
题意: 求[L, R]范围内, 不含有数字4和62的数的个数。
记忆搜索的写法非常简单,已加入模板。
#include<bits/stdc++.h>
using namespace std;
int dp[15][2];
int num[15];
int dfs(int pos, int st, int f){ // st值 0表示不含4且不以6结尾 1表示不含4且以6结尾 2表示含有了4或者62,转移时其实直接舍去了,无需关注
if(pos < 1) return 1; // 到0就返回啦 表示所有位都填上了一个数 并且是合法的
if(!f && dp[pos][st] != -1) return dp[pos][st]; //如果已经搜过了就不用再搜了
int end = f? num[pos] : 9;
int ans = 0;
for(int i = 0; i <= end; ++i){
if(i == 4 || (st == 1 && i == 2)) continue; //当已出现4或者62的时候就不用搜了,搜了也肯定舍去
else if(i == 6) ans += dfs(pos-1, 1, f && i == end);
else ans += dfs(pos-1, 0, f && i == end);
}
if(!f) dp[pos][st] = ans; // 记忆化
return ans;
}
int solve(int n){ //返回 [0, n]区间内不含4和62的个数
int len = 0;
while(n){
num[++len] = n%10; // 位置0并没有定义
n /= 10;
}
return dfs(len, 0, 1);
}
int main(){
int n, m;
memset(dp, -1, sizeof(dp)); //此题是不需要重复初始化的
while(scanf("%d%d", &n, &m), n||m){
printf("%d\n", solve(m)-solve(n-1)); //要注意n-1会不会为负
}
}
题意:求[0, N]范围内,含49的数的个数,和上面类似。
#include<bits/stdc++.h>
#define ll long long int
using namespace std;
ll dp[25][3];
int num[25];
ll dfs(int pos, int st, int f){ // st值 0表示不含49且不以4结尾 1表示不含49且以4结尾 2表示含有49
if(pos < 1) return st == 2; // 这题求含有49的,那就返回状态2
if(!f && dp[pos][st] != -1) return dp[pos][st];
int end = f? num[pos] : 9;
ll ans = 0;
for(int i = 0; i <= end; ++i){
if(st == 2 || (st == 1 && i == 9)) ans += dfs(pos-1, 2, f && i == end);
else if(i == 4) ans += dfs(pos-1, 1, f && i == end);
else ans += dfs(pos-1, 0, f && i == end);
}
if(!f) dp[pos][st] = ans;
return ans;
}
ll solve(ll n){
int len = 0;
while(n){
num[++len] = n%10;
n /= 10;
}
return dfs(len, 0, 1);
}
int main(){
int T;
memset(dp, -1, sizeof(dp));
scanf("%d", &T);
while(T--){
ll n;
scanf("%lld", &n);
printf("%lld\n", solve(n));
}
}