hdu-4734 F(x)

F(x)

Time Limit: 1000/500 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

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).
 
(我还是翻译一下吧,不然哪天我自己都读不懂了(>_<))
(对于一个有n位(这n位从高位到低位分别是AnAn-1An-2 ... A2A1)的十进制数,我们定义它的权值F(x)=An * 2n-1 + An-1 * 2n-2 + ... + A2 * 2 + A1 * 1.现在给你两个数A,B,请计算[0,B]范围内有多少个权值<=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

 

Recommend
liuyiding   |   We have carefully selected several similar problems for you:  6216 6215 6214 6213 6212 
 
 
Solution
数位dp.
dp[i][j]表示枚举到第i位,剩下的数位的权值和的限制为<=j
很正常的一道数位dp.
但是我很智障,Case的第一个大写打成了小写,莫名其妙地wa了,差点就开始对拍了.还是懒一点比较好,直接复制过来.
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
int mi[13],dp[13][4611],oo[13];
inline int read()
{
	register int ans=0,f=1;char ch=getchar();
	while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
	while(isdigit(ch)) {ans=ans*10+ch-'0';ch=getchar();}
	return ans*f;
}
inline int reada()
{
	register int ans=0,f=1;char ch=getchar();
	while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
	while(isdigit(ch)) {ans=ans*2+ch-'0';ch=getchar();}
	return ans*f;
}
int dfs(int wi,int cha,int lim)
{
	if(wi<1) return 1;
	if(!lim&&dp[wi][cha]>-1) 
	  return dp[wi][cha];
	int o=lim? oo[wi]:9;
	int ans=0;
	for(int i=0;i<=o;i++)
	{
		if(i*mi[wi-1]>cha)
		  break;
		ans+=dfs(wi-1,cha-i*mi[wi-1],lim&&i==oo[wi]);
	}
	if(!lim) dp[wi][cha]=ans;
	return ans;
}
int sol(int a,int b)
{
	int w=0;
	while(b)
	{
		oo[++w]=b%10;
		b/=10;
	}
	return dfs(w,a,1);
}
int main()
{
	int cas,a,b;       ///case重名 
	cas=read();
	mi[0]=1;
	for(int i=1;i<=10;i++)
	  mi[i]=2*mi[i-1];
	memset(dp,-1,sizeof(dp));
	for(int i=1;i<=cas;i++)
	{
		a=reada();b=read();
		printf("Case #%d: ",i);
		printf("%d\n",sol(a,b));
	}
	return 0;
}
posted @ 2017-09-28 20:04  o00v00o  阅读(377)  评论(0编辑  收藏  举报