题意:给出F()函数 求在[0 - B]中有多少个数的F值小于F(A)
方法一:预处理 dp[i][j][st] 表示第i位为j 时 F值不大于st的个数
转移方程 dp[i][j][st] = ∑dp[i - 1][k][st - j * (2^(i -1))]
代码:
#include <cstdio>
#include <iostream>
#include <queue>
#include <cstring>
#define sf scanf
#define pf printf
using namespace std;
typedef long long LL;
const int max_st = 9 * (2 << 10) + 50;
int dp[15][10][max_st];
void init_dp(){
memset(dp,0,sizeof(dp));
for(int i = 0;i < 10;++i) dp[1][i][i] = 1;
for(int i = 0;i < 10;++i){
for(int j = i + 1;j < max_st;++j){
dp[1][i][j] += dp[1][i][j - 1];
}
}
for(int i = 2;i < 11;++i){
for(int j = 0;j < 10;++j){
int temp = j * (1 << (i - 1));
for(int p = temp;p < max_st;++p){
for(int k = 0;k < 10;++k){
dp[i][j][p] += dp[i - 1][k][p - temp];
}
}
}
}
}
int digit[15];
int solve(int A,int B){
int f_a = 0,temp = 1;
while(A){
f_a = f_a + (A % 10)*temp;A = A / 10;
temp <<= 1;
}
int len = 0;
while(B){ digit[++len] = B % 10;B = B / 10;}
int pre_sum = 0,ret = 0;
for(int i = len;i;--i){
for(int j = 0;j < digit[i];++j){
ret += dp[i][j][f_a - pre_sum];
}
pre_sum = pre_sum + digit[i] * (1 << (i - 1));
if(pre_sum > f_a) break;
}
return ret;
}
int main(){
init_dp();
int T,ca = 0,A,B;
sf("%d",&T);
while( T-- ){
sf("%d%d",&A,&B);
pf("Case #%d: %d\n",++ca,solve(A,B + 1));
}
return 0;
}
方法二: DFS
代码:
#include <cstdio>
#include <iostream>
#include <queue>
#include <cstring>
#define sf scanf
#define pf printf
using namespace std;
typedef long long LL;
const int max_st = 9 * (2 << 10) + 50;
int dp[15][max_st];//dp[i][st] 第i位 f值不大于st的个数
int digit[15];
int f_a;
int dfs(int i,int st,bool flag){
if(st < 0) return 0;
if(!i) return dp[i][st] = !flag;
if(!flag && ~dp[i][st]) return dp[i][st];
int ans = 0;
int limit = flag ? digit[i] : 9;
int temp = 1 << (i - 1) ;
for(int j = 0;j <= limit;++j){
ans += dfs(i - 1,st - j * temp,flag && j == limit);
}
if(!flag) dp[i][st] = ans;
return ans;
}
int solve(int A,int B){
int len = 0,fa_a = 0,temp = 1;
while(B){
digit[++len] = B % 10;B = B / 10;
}
while(A) {fa_a = fa_a + (A % 10) * temp;A = A / 10;temp = temp << 1;}
return dfs(len,fa_a,1);
}
int main(){
memset(dp,-1,sizeof(dp));
int T,ca = 0;sf("%d",&T);
int A,B;
while( T-- ){
sf("%d%d",&A,&B);
pf("Case #%d: %d\n",++ca,solve(A,B + 1));
}
return 0;
}