[bzoj1419]Red is good 题解
[bzoj1419]Red is good 题解
我真的是服了,没想到被一个 不能四舍五入 给坑惨了。
推导
因为指派是线性排放,很容易想到线性DP。设 表示取了 个红牌, 个黑牌的期望。
对于 ,很容易想到有两种:
- 上一个拿了一个红牌:值为 ,概率为 。
- 上一个拿了一个黑牌:值为 ,概率为 。
所以推导公式为:
因为是在最优情况下,所以当 时,令 。
下面开始头疼的环节:如何不四舍五入?其实并不难,但是被精度卡就很难受。
代码放上,祥建注释:
void print(double printion) {
long long fixing = printion * 1000000 * 10; // 1000000取出后6位,再×10取出判断四舍五入的一位(注意开long long,卡了我30min)
fixing = (fixing - fixing % 10) / 10; // 删去判断四舍五入的一位
double ans = fixing * 1.0 / 1000000; // 直接除就可以了
printf("%.6lf", ans); // printf
}
举个例子:41.666666666...
-
四舍五入:41.666667
-
我的输出:41.666666
第一步,fixing = 416666666
;
第二步,fixing = (416666666 - 416666666 % 10) / 10 = 41666666
;
第三步,ans = 41666666 * 1.0 / 1000000 = 41.666666
。
代码
#include <bits/stdc++.h>
#define Maxn 5005
using namespace std;
int n, m; // n -- Red;m -- Black
double dp[3][Maxn];
void print(double printion) {
long long fixing = printion * 1000000 * 10;
fixing = (fixing - fixing % 10) / 10;
double ans = fixing * 1.0 / 1000000;
printf("%.6lf", ans);
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cin >> n >> m;
for (int i = 1; i <= n; i ++) {
dp[1][0] = i;
for (int j = 1; j <= m; j ++) {
dp[1][j] = (dp[0][j] + 1) * i * 1.0 / (i + j) + (dp[1][j - 1] - 1) * j * 1.0 / (i + j);
if (dp[1][j] < 0.0) { dp[1][j] = 0.0; }
} for (int j = 1; j <= m; j ++) {
dp[0][j] = dp[1][j];
}
}
// print(41.66666666666);
print(dp[1][m]);
return 0;
}
由于内存只有 ,我还用了一个 轮换数组(自己编的名字),就是将两行轮换使用,节省内存。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本