For a decimal number x with n digits (A nA n-1A n-2 … A 2A 1), we define its weight as F(x) = A n * 2 n-1 + A n-1 * 2 n-2 + … + A 2 * 2 + A 1 * 1. Now you are given two numbers A and B, please calculate how many numbers are there between 0 and B, inclusive, whose weight is no more than F(A).
Input
The first line has a number T (T <= 10000) , indicating the number of test cases.
For each test case, there are two numbers A and B (0 <= A,B < 10 9)
Output
For every case,you should output “Case #t: ” at first, without quotes. The t is the case number starting from 1. Then output the answer.
Sample Input
3
0 100
1 10
5 100
Sample Output
Case #1: 1
Case #2: 2
Case #3: 13
我们定义十进制数x的权值为f(x) = a(n)*2^(n-1)+a(n-1)*2(n-2)+…a(2)*2+a(1)*1,a(i)表示十进制数x中第i位的数字。
题目给出a,b,求出0~b有多少个不大于f(a)的数。
一开始想复杂了。。把自己难晕。。以为要比较每一位。。但其实。。很简单的直接统计就行,唯一确定的状态不大好想。。。第二位是余数。。的确余数就可以保证状态唯一了。。。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int wei[30];
int dp[30][8000];
int jin[30];
void init(){
jin[0]=1;
for(int i=1;i<=9;i++)
jin[i]=jin[i-1]*2;
}
int dfs(int pos,int pre,int flag)
{
if(pos<0)
{
return pre>=0;
}
if(!flag&&dp[pos][pre]!=-1)
{
return dp[pos][pre];
}
int up=flag?wei[pos]:9;
int res=0;
for(int i=0;i<=up;i++)
{
if(pre-i*jin[pos]>=0)
res+=dfs(pos-1,pre-i*jin[pos],flag&&up==i);
}
if(!flag)
{
dp[pos][pre]=res;
}
return res;
}
int cal(int x,int y)
{
int len=0;
while(x)
{
wei[len++]=x%10;
x/=10;
}
int tem=1;
int pre=0;
for(int i=0;i<len;i++)
{
pre+=tem*wei[i];
tem*=2;
}
len=0;
while(y)
{
wei[len++]=y%10;
y/=10;
}
return dfs(len-1,pre,1);
}
int main()
{
int t;
cin>>t;
init();
memset(dp,-1,sizeof(dp));
for(int f=1;f<=t;f++)
{
int a,b;
cin>>a>>b;
printf("Case #%d: %d\n",f,cal(a,b) );
}
}