关于此题[ABC350E] Toward 0和[ABC188F] +1-1x2记忆化搜索的一些总结
传送门1
传送门2
这两道题都有个特性,那就是数据范围到了
但是实际上我们可以用map。有人会说,用map那时间上貌似也过不去啊!但是我们发现这两道题当中,我们可以进行的操作都有除法操作,这就有点像势能线段树,时间复杂度实际上是log级别的。
对于第一题期望DP,我们显然是DP不了了,因为没法一个个转移,只能记忆化搜索,假设dp[u]表示从u到0的期望最小花费,那么此时我们有两条路,一条是选第一种操作方法,即花费
我们发现这个式子有后效性,那么就可以高斯消元(我也不会这题也没必要,或者移项即可:
于是这道题就被解决了。
代码:
#include<bits/stdc++.h>
using namespace std;
long long t;
const long long N = 2e5 + 10;
long long n,a,x,y;
map<long long,long double> dp;
long double dfs(long long m) {
if(m == 0) return 0;
if(dp[m]) return dp[m];
dp[m] = dfs(m/a) + x;
dp[m] = min(dp[m],1.0l / 5.0l * (dfs(m/2) + dfs(m/3) + dfs(m/4) + dfs(m/5) + dfs(m/6)) + 6.0l / 5.0l * (double)y);
return dp[m];
}
void solve() {
cin >> n >> a >> x >> y;
cout << fixed << setprecision(7) << dfs(n);
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
t = 1;
while(t--) solve();
return 0;
}
对于第二道题:
同样的,我们设
-
如果此时u<x,那么x只能一个一个减到达u,答案也就是x-u
-
如果此时u>x,那么有一个显而易见的答案u-x,但是由于还有乘法操作,对于u我们再分类讨论:
- 如果此时u是2的倍数,那么u可以从
来,所以此时用来更新答案的就是 - 如果此时u不是2的倍数,那么u可以从
或者 经过两次操作而来,此时用来更新答案的就是
而至于为什么不从x出发通过乘2来到y(因为我一开始就是这么做的),这样会TLE
代码:
#include<bits/stdc++.h>
using namespace std;
long long t;
long long x,yy;
map<long long,long long> dp;
long long dfs(long long y) {
if(x == y) return 0;
if(dp[y]) return dp[y];
if(x < y) {
dp[y] = y - x;
if(y % 2 == 0)
dp[y] = min(dp[y],dfs(y/2) + 1);
else
dp[y] = min(dp[y],min(dfs((y + 1) / 2) + 2,dfs((y - 1) / 2) + 2));
}
else dp[y] = x - y;
return dp[y];
}
void solve() {
cin >> x >> yy;
cout << dfs(yy);
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
t = 1;
while(t--) solve();
return 0;
}
2025.1.12更新:
再来一道(以后要是碰见一样的还不会做我吃了,ABC300 E - Dice Product 3
转移的方程和第一题一样,只不过少了个Y,因为这道题中没有花费
题目要求分数的模,由递推式可知分数的分母是5,于是求一下逆元即可
代码:
#include<bits/stdc++.h>
using namespace std;
const long long mod = 998244353;
long long t;
long long n,tmp;
map<long long,long long> dp;
long long quickMul(long long x,long long k) {
if(k == 0) return 1;
long long tp = quickMul(x,k/2);
tp = (tp * tp) % mod;
if(k % 2) tp = (tp * x) % mod;
return tp;
}
long long dfs(long long u) {
if(u == 1) return 1;
if(dp[u]) return dp[u];
long long res = 0;
if(u % 2 == 0) res += dfs(u/2);
if(u % 3 == 0) res += dfs(u/3);
if(u % 4 == 0) res += dfs(u/4);
if(u % 5 == 0) res += dfs(u/5);
if(u % 6 == 0) res += dfs(u/6);
dp[u] = ((res % mod) * (tmp % mod)) % mod;
return ((res % mod) * (tmp % mod)) % mod;
}
void solve() {
cin >> n;
tmp = quickMul(5,mod-2);
cout << dfs(n);
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
t = 1;
while(t--) solve();
return 0;
}
分类:
做题总结