http://acm.hdu.edu.cn/showproblem.php?pid=4734
这道题的dp数组存的实际上是低某些位能凑到sum的种类数,虽然仍然是从高位到低位遍历
因为A是会变得,但是低位能凑到多少是不变的,所以这样反过来想的话就不需要重新memset了。
这也是数位dp优化中的一个重要思想。
#include<bits/stdc++.h>
using namespace std;
int dp[22][5555];
int a[22];
int fa;
int f(int x)
{
if(!x)return 0;
int ans=f(x/10);
return ans*2+(x%10);
}
int dfs(int pos,int sum,int limit)
{
if(pos==-1)return sum<=fa;
if(sum>fa)return 0;
if(!limit&&dp[pos][fa-sum]!=-1)return dp[pos][fa-sum];
int to;
if(limit)
to=a[pos];
else to=9;
int ans=0;
for(int i=0;i<=to;i++)
{
ans+=dfs(pos-1,sum+i*(1<<pos),limit&&i==a[pos]);
}
if(!limit)
dp[pos][fa-sum]=ans;
return ans;
}
int solve(int x)
{
int js=0;
while(x)
{
a[js++]=x%10;
x/=10;
}
return dfs(js-1,0,1);
}
int main(){
int t;
cin>>t;
memset(dp,-1,sizeof(dp));
int cs=1;
while(t--)
{
int a,b;
cin>>a>>b;
fa=f(a);
cout<<"Case #"<<cs++<<": ";
cout<<solve(b)<<endl;
}
return 0;
}