您的位置:首页 > 其它

HDU 4734 F(x)【数位DP】

2016-11-15 20:34 369 查看
题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=4734

F(x)

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

Total Submission(s): 4874 Accepted Submission(s): 1809

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

2013 ACM/ICPC Asia Regional Chengdu Online

【中文题意】给你a和b的值,给你了F(x)的求法,让你求在(0,B)上求比F(a)小的数的个数。

【思路分析】明显就是数位DP。数位DP+记忆化搜索,可以很快求出数字的个数,解释都在AC代码中。

【AC代码】

#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;

int dp[20][10000],dight[20];
int dfs(int pos,int pre,bool limit)//pre一开始记录F(a)的值
{
if(pos==-1)
{
return pre>=0;
}
if(pre<0)
{
return 0;
}
if(dp[pos][pre]!=-1&&!limit)
{
return dp[pos][pre];
}
int re=0;
int tmp=limit?dight[pos]:9;
for(int i=0;i<=tmp;i++)
{
re+=dfs(pos-1,pre-i*(1<<pos),limit&&i==tmp);
}
if(!limit)
{
dp[pos][pre]=re;
}
return re;
}

int cal(int a,int b)//计算0和b之间符合条件的数的个数
{
int re=0,len1=0,len2=0;
while(a)
{
re+=(a%10)*(1<<len1);
len1++;
a/=10;
}
while(b)
{
dight[len2++]=b%10;
b/=10;
}
return dfs(len2-1,re,1);
}

int main()
{
int t,a,b,iCase=0;
memset(dp,-1,sizeof(dp));
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&a,&b);
printf("Case #%d: %d\n",++iCase,cal(a,b));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  dp