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;
}