数位DP_ HDU 4734

这个题意思是每一个数都有一个对应的权值,比如一个数字a有n位数,那么他的权值为F(a) =  A* 2n-1 + An-1 * 2n-2 + ... + A2 * 2 + A1 * 1 ,这里的Ai表示数字a的第i位数,那么给两个数字a  b,求解在区间[0,b]中有多少数字满足:F(x)>= F(a)

看到这个题,我们也可以想到这个权值的大小和数字的大小没有任何关系,只是和数位上的数字有关系,并且求解的是区间内成立个数的问题,那么就可以想到是个区间DP问题

但是我们要是记录状态的话:dp[i][j]:当前位置为i,并且现在前i位的权值已经为j的情况下,后面满足条件的个数,如果这样定义状态的话,那么每次输入都要去更新dp数组了,因为每次给出的F(a)都是不同的,也就是当F(a)不同的情况下,dp[2][50]的数值只是对当前计算的F(a)是有效的

如果向上面所说的,那我们定义dp[i][j][val]:当前位置为i、F(a) = val 、前i为的权值已经为j的情况下,后面满足条件的个数,这样的话实质上和我们上面的情况没有什么区别,只不过是牺牲了空间,时间确实得到了提升,并且在这个题中最大的val大约为2600,这样的话空间还可以,但是在其他的题目中val可能就不止这些,所以这个还有可能会内存超限

那么我们看一下解决的办法:既没有牺牲空间、时间也会得到提升

我们知道不管F(a)是什么数值,那么比如在已经知道前i位的权值为x情况下,那么后面几位最大的能够到达的权值已经确定了,也就是F(a) - x,那么当再次到达这个位置时,后面权值最多再次到达 F(a) - x的话,我们就可以用前面的那个状态了,所以我们就可以用   dp[i][j]:当前位置为i、后面最多能够使用的权值为j的情况下,满足条件的个数 

那么这样我们确定了状态的表示,那么剩下的大概就是数位DP的模板题了

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iomanip>
#include <cmath>
#include <vector>
#include <set>
#include <queue>
#include <map>
#include <math.h>
#include <cmath>
#define INF 0x3f3f3f3f

using namespace std;
const int MAXN = 5000;
int dp[10][MAXN];
int a[10];
int F(int x)
{
    if(x == 0) return 0;
    int ans = F(x/10);
    return ans * 2 + x % 10;
}
int all;
int dfs(int pos,int sum,bool limit)
{
    if(pos < 0) return sum <= all;
    if(sum > all) return 0;
    if(!limit && dp[pos][all - sum] != -1) return dp[pos][all-sum];
    int up = limit?a[pos]:9;
    int ans = 0;
    for(int i = 0;i <= up;i ++)
        ans += dfs(pos-1,sum + i * (1<<pos), limit && i == a[pos]);
    if(!limit) dp[pos][all - sum]  = ans;
    return ans;
}
int Solve(int x)
{
    int pos = 0;
    while(x)
    {
        a[pos ++] = x % 10;
        x /= 10;
    }
    return dfs(pos-1 , 0, true);
}
int main()
{
    int T,a,r;
    scanf("%d",&T);
    int cas = 1;
    memset(dp,-1,sizeof(dp));
    while(T--)
    {
        scanf("%d%d",&a,&r);
        all = F(a);
        printf("Case #%d: %d\n",cas++,Solve(r));
    }

}

参考博客

https://blog.csdn.net/wust_zzwh/article/details/52100392

猜你喜欢

转载自blog.csdn.net/li1615882553/article/details/80204758