湖南集训 大新闻 社论

大新闻

有一个在 [0,n) 内等概率随机选择的整数,记其为 x . 我们需要在 [0,n) 内找到某一个整数 y,使得 xy 达到最大值 .

问题在于,有可能对 x 进行了加密 . 情报显示,没有被加密的概率为 p . 我们决定采取这样的策略:如果 x 没有被加密,那么我们选出使得 xy 最大的 y;否则,我们在 [0,n) 内等概率随机选择一个整数作为 y .

xy 的期望 .

n1018 .

你们搞的这个题啊,exciting!

显而易见令 p1 是加密过的期望,p2 是没加密过的期望,则答案为

(1p)p1+pp2

可以发现,

p1=1n2i=0n1j=0n1(ij)p2=1ni=0n1maxj[0,n)(ij)


p1 求法

根据期望线性性我们可以按位考虑,于是

p1=i=0logn2qi(1qi)2i

其中 qi 为从 [0,n) 均匀随机选出一个数,其二进制第 i 位为 1 的概率 .

算出第 i 位为 1 的个数即可得到

ak=1n(2kn2k+1+max{nmod2k+12k,0})

这样暴力算就是 O(logn) 的了 .


p2 求法

一个贪心策略:设最优匹配为 y,从高到低按位考虑,如果 x 这位是 1 就跳过,不然如果 y 加上这一位对应的值仍然小于 n 就加上 . 根据字典序的原理这显然是对的 .

然而我们要求一行的这个玩意,考虑一个类似数位 DP 的东西,我们算一下前 i 位和 n1 的前 i 位相同的所有 x 产生的贡献,设 x 的最优匹配为 y,分讨一下:

  • n1 的第 i 位为 0 . 则 x,y 的第 i 位亦为 0,这时对答案没有什么影响 .
  • n1 的第 i 位为 1,则 x,y 的第 i 位必然互为反,但是当 x 的第 i 位为 1 时,后面还会有限制 .

一次递归规模至少减半,所以这个也是 O(logn) 的,于是总复杂度就是 O(logn) 了 .

核心代码:

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;
}
posted @   yspm  阅读(115)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
😅​
点击右上角即可分享
微信分享提示