您的位置:首页 > 其它

HDU 4734 F(x) (数位DP)

2014-12-22 21:13 369 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4734

题意:给你两个数 a、b,F(x) = An * 2n-1 +An-1 *
2n-2 + ... + A2 *2
+ A1 * 1,A是X十进制各个数位上的数字,让你求出 0 ~ b 中f(x) 比f(a)小的数字个数。

思路:数位DP,dp[len][num] 代表长度为len下且权值不大于num的符合条件的数的个数

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <vector>
#include <cstring>
#include <functional>
#include <utility>
#include <queue>
#include <set>
#include <map>

using namespace std;

int a, b;
int dp[20][10000];
int bit[20];

int dfs(int pos, int num, int lim)
{
if(pos < 0)
return num >= 0;
if(num < 0) return 0;
if(!lim && dp[pos][num] != -1)
return dp[pos][num];
int sum = 0;
int ri = lim ? bit[pos] : 9;
for(int i = 0; i <= ri; i++)
{
sum += dfs(pos - 1, num - i * (1 << pos), lim && i == ri); //判断对下一位的数值有无约束
}
if(!lim) //记忆化搜索
dp[pos][num] = sum;
return sum;
}

int val(int x)
{
int ans = 0;
int len = 0;
while(x)
{
ans += (x % 10) * (1 << len);
x /= 10;
len++;
}
return ans;
}

int solve()
{
int len = 0;
while(b)
{
bit[len++] = b % 10;
b /= 10;
}
return dfs(len - 1, val(a), 1);
}

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