1. 程式人生 > >4734 F(x) 數位dp

4734 F(x) 數位dp

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

題解:dp[i][j] 表示第i位0的個數-1的個數的數量  因為可能為負數 ,所以 初始化為35 (輸入轉換2進位制最多32位)

要從第一個不是0的位置開始計算,所以 在模板的情況下加一個lead即可

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
#define PI acos(-1)
const int N=1e5+10;
#define eps 0.00001
int dp[35][65];
int wei[35];
int dfs(int pos,int st,int lead,int limit)
{
	if(pos==0)
	{
		//cout<<st<<endl;
		return st>=35;
	}
	if(!limit&&!lead&&dp[pos][st]!=-1) return dp[pos][st];
	int en=limit?wei[pos]:1;
	int ans=0;
	for(int i=0;i<=en;i++)
	{
	//	cout<<st<<" "<<i<<" "<<pos<<endl;
		if(lead&&i==0) ans+=dfs(pos-1,st,lead,limit&&i==en);
		else ans+=dfs(pos-1,st+(i==0?1:-1),lead&&i==0,limit&&i==en);
	}
	if(!lead&&!limit) dp[pos][st]=ans;
	return ans;
}
int solve(int x)
{
	int len=0;
	while(x)
	{
		wei[++len]=x&1;
		x>>=1;
	}
	return dfs(len,35,1,1);
}
int main()
{
	memset(dp,-1,sizeof(dp));
	int a,b;
	while(~scanf("%d%d",&a,&b))
	{
		//cout<<solve(b)<<" "<<solve(a-1)<<endl;
		printf("%d\n",solve(b)-solve(a-1));
	}
	return 0;
}