#include<iostream>
#include<cstdio>
#include<list>
#include<algorithm>
#include<cstring>
#include<string>
#include<queue>
#include<stack>
#include<map>
#include<vector>
#include<cmath>
#include<memory.h>
#define ll long long
#define LL __int64
using namespace std;
int dp[10][4700];// dp[i][j]表示i位数,函数值小于等于j的有多少个
int degree[12];
int c[12];
void init()//预处理
{
degree[0]=1;
for(int i=1;i<=10;i++)
degree[i]=degree[i-1]<<1;
dp[0][0]=1;
for(int i=1;i<=8;i++)
{
for(int j=0;j<=4600;j++)
if(dp[i-1][j]>0)
for(int k=0;k<10;k++)
dp[i][k*degree[i-1]+j]+=dp[i-1][j];
}
for(int i=0;i<=8;i++)
for(int j=1;j<=4600;j++)
dp[i][j]+=dp[i][j-1];
}
int main()
{
init();
int a,b,t,Case=0;;
cin>>t;
while(t--)
{
scanf("%d %d",&a,&b);
int m=0,x=1;
while(a)
{
m+=(a%10)*x;
x=x<<1;
a=a/10;
}
int cnt=0;
while(b)
{
c[++cnt]=b%10;
b=b/10;
}
int ans=0;
for(int i=cnt;i>=1;i--)
{
for(int j=0;j<c[i];j++)
{
int tmp=m-j*degree[i-1];
if(tmp>=0)
ans+=dp[i-1][tmp];
}
m-=c[i]*degree[i-1];
if(m<0)break;
}
if(m>=0)
ans++;
printf("Case #%d: %d\n",++Case,ans);
}
return 0;
}
上面那个是预处理法
下面这个是递归法:
#include<iostream>
#include<cstdio>
#include<list>
#include<algorithm>
#include<cstring>
#include<string>
#include<queue>
#include<stack>
#include<map>
#include<vector>
#include<cmath>
#include<memory.h>
#define ll long long
#define LL __int64
using namespace std;
char b[12];
int dp[12][4600];
int degree[12];
int Len;
void clear()
{
memset(b,0,sizeof(b));
memset(dp,-1,sizeof(dp));
}
void init()
{
for(int i=0;i<11;i++)
degree[i]=1<<i;
}
int dfs(int len,int sum,int flag)
{
if(len==-1)
{
if(sum>=0)
return 1;
else
return 0;
}
if(sum<0)
return 0;
if(!flag && dp[len][sum]!=-1)
return dp[len][sum];
int ans=0,x,i;
x=(flag?b[Len-len-1]-'0':9);
for(i=0;i<=x;i++)
ans+=dfs(len-1,sum-i*degree[len],flag&&(i==x));
if(!flag)
return dp[len][sum]=ans;
return ans;
}
int main()
{
int t,a,Case=0;
cin>>t;
init();
clear();
while(t--)
{
scanf("%d %s",&a,b);
int sum=0,x=1;
while(a)
{
sum+=(a%10)*x;
a/=10;
x<<1;
}
Len=strlen(b);
int ans=dfs(Len-1,sum,1);
printf("%d\n",ans);
}
return 0;
}