题意:F(x) = An * 2n-1 + An-1 * 2n-2 + ... + A2 * 2 + A1 * 1,Ai是十进制数位,然后给出a,b求区间[0,b]内满足f(i)<=f(a)的i的个数。
比较常规的数位dp
dp[i][j]:低于i位数字的数中小于j的个数。
然后从高位到第位进行数位dp,记录前面位累加的F贡献。
减去小于FA,和超上界。 搞搞就行
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5+7;
int di[20];
ll dp[20][10000+7];//i位数内小于j的数的个数
ll dfs(int len,int num,bool limit)//当前位len,前面位已经对F产生了num的贡献,是否达到上界
{
if(len==0)return 1;
if(!limit&&dp[len][num])return dp[len][num];
int upl=limit?di[len]:9;
ll ans=0;
for(int i=0;i<=upl;i++)
{
int tp=i*(1<<(len-1));
if(tp>num)break;//累加的数大于F(A),剪枝
ans+=dfs(len-1,num-tp,i==upl&&limit);//上界的条件是:上一位到上界,且这一位也到了上界
}
if(!limit)dp[len][num]=ans;
return ans;
}
ll cal(ll A,ll B)
{
int k=0;
while(B)
{
di[++k]=B%10;
B/=10;
}
int ans=0,tp=1;
while(A)
{
ans+=A%10*tp;
A/=10;tp*=2;
}
//cout<<ans<<endl;
return dfs(k,ans,true);
}
int main()
{
int t;
scanf("%d",&t);
for(int i=1;i<=t;i++)
{
ll A,B;
scanf("%lld%lld",&A,&B);
printf("Case #%d: %lld\n",i,cal(A,B));//计算了0,多减 就要加回来1
}
return 0;
}