湖南集训 大新闻 社论
大新闻
有一个在 内等概率随机选择的整数,记其为 . 我们需要在 内找到某一个整数 ,使得 达到最大值 .
问题在于,有可能对 进行了加密 . 情报显示,没有被加密的概率为 . 我们决定采取这样的策略:如果 没有被加密,那么我们选出使得 最大的 ;否则,我们在 内等概率随机选择一个整数作为 .
求 的期望 .
.
你们搞的这个题啊,exciting!
显而易见令 是加密过的期望, 是没加密过的期望,则答案为
可以发现,
求法:
根据期望线性性我们可以按位考虑,于是
其中 为从 均匀随机选出一个数,其二进制第 位为 的概率 .
算出第 位为 的个数即可得到
这样暴力算就是 的了 .
求法:
一个贪心策略:设最优匹配为 ,从高到低按位考虑,如果 这位是 就跳过,不然如果 加上这一位对应的值仍然小于 就加上 . 根据字典序的原理这显然是对的 .
然而我们要求一行的这个玩意,考虑一个类似数位 DP 的东西,我们算一下前 位和 的前 位相同的所有 产生的贡献,设 的最优匹配为 ,分讨一下:
- 的第 位为 . 则 的第 位亦为 ,这时对答案没有什么影响 .
- 的第 位为 ,则 的第 位必然互为反,但是当 的第 位为 时,后面还会有限制 .
一次递归规模至少减半,所以这个也是 的,于是总复杂度就是 了 .
核心代码:
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int, int> pii;
db p1(ll n)
{
db ans = 0;
ll power = 0, _ = n-1;
while (_){++power; _ >>= 1;}
for (int i=power; i; i--)
{
ll tmp = (n >> i) * (1ll << (i-1)) + min(n - (n >> i << i), 1ll << (i-1));
ans += (1 - 1. * (n - tmp) / n) * (1ll << (i-1)) * (n - tmp) / n;
} return ans * 2;
}
db p2(ll n)
{
if (n == 1) return 0;
db ans = 0;
ll v = 1, d, _ = --n;
while (v <= _) v <<= 1;
d = v - 1; v >>= 1;
ans += 1. * d * (n-v+1) + 1. * v * v;
ll now = v; d >>= 1;
while (v > 1)
{
v >>= 1; d >>= 1;
if (n & v){ans += 1. * now * v + 1. * (now >> 1) * d; now >>= 1;}
else ans += 1. * (now >> 1) * v;
}
return ans / (n + 1);
}
ll n; db p;
int main()
{
scanf("%lld%lf", &n, &p);
printf("%.6f\n", (1-p) * p1(n) + p * p2(n));
return 0;
}
以下是博客签名,正文无关
本文来自博客园,作者:yspm,转载请注明原文链接:https://www.cnblogs.com/CDOI-24374/p/16573516.html
版权声明:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议(CC BY-NC-SA 4.0)进行许可。看完如果觉得有用请点个赞吧 QwQ
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】