【数位DP(Sub)】HDU 4734 F(x)

HDU 4734 F(x)

思路:

  • dfs里的cnt指的是当前pos位往前已经有了cnt的价值和。

  • 例如211。第2位2,对应的cnt = 0

  • 第1位1,对应的cnt = 0 + 2*(1 << 2) = 8

  • 第0位1,对应的cnt = 8 + 1*(1 << 1) = 10

  • 第-1位,对应的cnt = 10 + 1*(1 << 0) = 11

  • 拿第-1位来说,就是所有数位的价值和有11

  • 拿第0位来说,就是第2和第1数位的价值和有了10

  • 接下来是dp[pos][tot - cnt],表示的是当前pos位还需要凑出来tot - cnt的价值

    关于数组大小:数位权值和最大不超过4599,也就是999999999的权值和,所以开5e3足够了

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <limits>
#include <set>
#include <queue>
#include <vector>
#include <stack>
#include <map>
#define INF 0x3f3f3f3f

using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxN = 5e3;
int A, B;
int a[35];
int dp[35][maxN];
int tot;
int f(int x)
{
    if(x == 0)
        return 0;
    return 2 * f(x / 10) + x % 10;
}
int dfs(int pos, int cnt, bool limit)
{
    if(pos == -1)
        return tot >= cnt;
    if(cnt > tot)
        return 0;
    if(!limit && dp[pos][tot - cnt] != -1)
        return dp[pos][tot - cnt];
    int up = limit ? a[pos] : 9;
    int ans = 0;
    for(int i = 0; i <= up; i ++ )
    {
        ans += dfs(pos - 1, cnt + i * (1 << pos), limit && i == a[pos]);
    }
    if(!limit)
        dp[pos][tot - cnt] = 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()
{
    memset(dp, -1, sizeof(dp));
    int T; scanf("%d", &T);
    for(int i = 1; i <= T; i ++ )
    {
        scanf("%d%d", &A, &B);
        tot = f(A);
        printf("Case #%d: %d\n", i, solve(B));
    }
    return 0;
}
  • 所以做过真的会忘。而且还发现之前理解的所谓相减是错的。当时还以为是人家博客写错了,原来是自己理解错了。
  • dfs中的sum指的是高位已经有了sum的价值和。而A - sum是指低位还需要多少的价值和。所以记忆话的也是dp[pos][A - sum]
  • 还有就是sum > A一定要放在最前面判断,否则A-sum就越界了啊qaq

这件事情提醒我们,温故而知新!还有就是接受新知识的时候真的很困难qaq

qaq

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxN = 1e5 + 5;
int A, B;
int a[20];
int dp[20][maxN];
int f(int x)
{
    if(x == 0)
        return 0;
    return 2 * f(x / 10) + x % 10;
}
int dfs(int pos, int sum, bool limit)
{
    if(pos == -1)
        return sum <= A;
    if(sum > A)
        return 0;
    if(!limit && dp[pos][A - sum] != -1)
        return dp[pos][A - 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][A - 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()
{
    memset(dp, -1, sizeof(dp));
    int T; scanf("%d", &T);
    for(int Case = 1; Case <= T; Case ++ )
    {
        scanf("%d%d", &A, &B);
        A = f(A);
        printf("Case #%d: %d\n", Case, solve(B));
    }
    return 0;
}
发布了180 篇原创文章 · 获赞 54 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_44049850/article/details/103846004