HDU4734(数位dp)

时间:2023-03-09 01:22:31
HDU4734(数位dp)

F(x)

Time Limit: 1000/500 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 4423    Accepted Submission(s): 1632

Problem Description

For a decimal number x with n digits (AnAn-1An-2 ... A2A1), we define its weight as F(x) = An * 2n-1 + An-1 * 2n-2 + ... + A2 * 2 + A1 * 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 < 109)

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

Source

 //2016.8.31
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include <cstdio>
#include <cstring> using namespace std; int dp[][], bit[], a, b;//dp[i][j]表示第i位<=j的数目 int F(int a)
{
int ans = , len = ;
while(a)
{
ans += (a%)*(<<len);
len++;
a /= ;
}
return ans;
} int dfs(int pos, int num, int fg)
{
if(pos == -)return num>=;
if(num < )return ;
if(!fg && dp[pos][num]!=-)//记忆化搜索
return dp[pos][num];
int ans = ;
int ed = fg?bit[pos]:;
for(int i = ; i <= ed; i++)
ans+=dfs(pos-, num-i*(<<pos), fg&&i==ed);
if(!fg)dp[pos][num] = ans;
return ans;
} int solve(int b)
{
int len = ;
while(b)
{
bit[len++] = b%;
b /= ;
}
int ans = dfs(len-, F(a), );
return ans;
} int main()
{
int T, kase = ;
cin>>T;
memset(dp, -, sizeof(dp));
while(T--)
{
scanf("%d%d", &a, &b);
int ans = solve(b);
printf("Case #%d: %d\n", ++kase, ans);
} return ;
}