题意:问0到B中按照公式的计算方法有多少数的值小于等于A的计算结果
思路:首先将A的计算结果计算出来,然后跑数位DP的dfs即可,但是注意这道题目不能搜到头的方法,那样会超时,所以我们可以判断一下现在的值如果已经大于A的计算结果,那么就没必要继续搜了
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3fll;
const int maxn=5010;
int dig[30],f[20];
ll dp[20][19000];
ll dfs(int pos,ll sum,int lim){
if(sum<0) return 0;
if(pos<0){
if(sum>=0) return 1;
else return 0;
}
if(!lim&&dp[pos][sum]!=-1) return dp[pos][sum];
int las=lim?dig[pos]:9;
ll ret=0;
for(int i=0;i<=las;i++) ret+=dfs(pos-1,sum-f[pos]*i,lim&&(i==las));
if(!lim) dp[pos][sum]=ret;
return ret;
}
ll slove(ll n,ll sum){
if(n==-1) return 0;
int len=0;
ll ret=0;
while(n){
dig[len++]=n%10;
n/=10;
}
return dfs(len-1,sum,1);
}
ll calc_sum(ll n){
ll tmp=1,ret=0;
while(n){
ret=ret+n%10*tmp;
tmp*=2;n/=10;
}
return ret;
}
void init(){
f[0]=1;
for(int i=1;i<20;i++) f[i]=f[i-1]*2;
}
int main(){
memset(dp,-1,sizeof(dp));
init();
int T,cas=1;
ll n,m;
scanf("%d",&T);
while(T--){
scanf("%I64d%I64d",&n,&m);
ll sum=calc_sum(n);
printf("Case #%d: %I64d\n",cas++,slove(m,sum));
}
return 0;
}