基本的数位dp这几天在学 ,巩固一下,记忆化 dp[i][j] 表示长度为i位的时候不超过j的数的种数 记录的时候就用f(a)减去当前的记录的sum值就是后面的不超过的值了
#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
#define MAXN 10
int dp[MAXN][5000];
int dat[20];
int dfs(int len,int sum,int maxnum,bool flag)
{
if(sum>maxnum)
return 0;
if(len<0)
return 1;
if(!flag&&dp[len][maxnum-sum]!=-1)
return dp[len][maxnum-sum];
int _end = flag?dat[len]:9;
int ans = 0;
for(int i = 0;i<=_end;i++)
{
ans += dfs(len-1,sum+i*(1<<len),maxnum,flag && i==_end);
}
// printf("dfs %d %d %d\n",len,sum,ans);
if(!flag)
{
dp[len][maxnum-sum] = ans;
}
return ans;
}
int Cal(int a,int b)
{
int len = 0;
int sum = 0;
int base = 1;
while(a!=0)
{
int Mod = a%10;
sum += Mod*base;
base <<= 1;
a/=10;
}
//printf("%d\n",sum);
while(b!=0)
{
int Mod = b%10;
dat[len++] = Mod;
b/=10;
}
return dfs(len-1,0,sum,true);
}
int main()
{
int t;
scanf("%d",&t);
int _case = 0;
memset(dp,-1,sizeof(dp));
while(t--)
{
int ta,tb;
scanf("%d%d",&ta,&tb);
printf("Case #%d: %d\n",++_case,Cal(ta,tb));
}
return 0;
}