测试20210422T1 Sample

博客内容讲述了如何使用二分查找方法解决一个数学优化问题,涉及期望得分的计算。通过构造函数和图像分析,找到最优解,并给出具体步骤和代码实现,强调在实际编程中需要注意精度问题。

在这里插入图片描述

​ 题解引用了拉格朗日乘数,但是我不会,所以讲一个更简单的方法。

​ 当 ppp 确定的时候,得分的期望应该是 2×∑i(pi−pi2)2\times\sum i(p_i-p_i^2)2×i(pipi2) 。令 f(p)=p−p2f(p)=p-p^2f(p)=pp2 然后画出它的图像

QQ图片20210422160054

​ 设最优解为 p∗p^*p ,那么任意 pa∗,pb∗p_a^*,p_b^*pa,pb 一定满足 af′(pa∗)=bf′(pb∗)af'(p_a^*)=bf'(p_b^*)af(pa)=bf(pb) 。这个很好理解,假设 af′(pa∗)>bf′(pb∗)af'(p_a^*)>bf'(p_b^*)af(pa)>bf(pb) ,则可以让 pa∗+xp_a^*+xpa+xpb∗−x,(x→0)p_b^*-x,(x\rightarrow0)pbx,(x0) ,于是 apa∗(1−pa∗)+bpb∗(1−pb∗)<a(pa∗+x)(1−(pa∗+x))+b(pb∗−x)(1−(pb∗−x))ap_a^*(1-p_a^*)+bp_b^*(1-p_b^*)<a(p_a^*+x)(1-(p_a^*+x))+b(p_b^*-x)(1-(p_b^*-x))apa(1pa)+bpb(1pb)<a(pa+x)(1(pa+x))+b(pbx)(1(pbx)) 显然这样 p∗p^*p 就不是最优的了。所以画出每一个 yi=if′(p)y_i=if'(p)yi=if(p) 的图像

QQ图片20210422160054

​ 和图中一样,我们现在只需要找到一个蓝线 l:y=Cl:y=Cl:y=C ,使得联立 yi=if′(p)y_i=if'(p)yi=if(p)y=Cy=Cy=C∑pi=1\sum p_i=1pi=1 。这个问题直接二分就可以了。
​ 这样我们就能求出 CCC,考虑如何求答案,因为 pi=i−C2ip_i=\frac{i-C}{2i}pi=2iiC ,所以答案的可以写成 ∑i>Ci2−C22i\sum_{i>C}\frac{i}{2}-\frac{C^2}{2i}i>C2i2iC2 。所以求出 CCC 后,我们可以直接计算出答案。总时间复杂度 O(Tlog⁡n)O(T\log n)O(Tlogn)

​ 写代码的时候注意精度问题,别二分进死循环了2333

#include <bits/stdc++.h>
#define N 1000006
using namespace std;
const double eps=1e-10;
const int maxn=1e6;
double n,inv[N],sum[N];
int nn;
void get_pos(double &mid){
	double l=0,r=n,now;
	while(r-l>eps){
		mid=(r+l)*0.5;
		if(mid==l||mid==r) break;
		now=n-floor(mid)-mid*(inv[nn]-inv[(int)floor(mid)]);
		if(now>2) l=mid;
		else r=mid;
	}
}
void work(){
	cin>>n; nn=n;
	if(n<=1){ printf("%.14lf\n",(double)0); return; }
	if(n==2){ printf("%.14lf\n",(double)1.5); return; }
	double pos=(n-2.0)/inv[nn],ans=0,o=0.5;
	get_pos(pos);
	ans=o*(sum[nn]-sum[(int)floor(pos)]-pos*pos*(inv[nn]-inv[(int)floor(pos)]));
	printf("%.14lf\n",ans);
}
void init(){
	for(double i=1;i<=maxn;i++)
		inv[(int)i]=inv[(int)i-1]+(double)1.0/i,
		sum[(int)i]=sum[(int)i-1]+i;
}
int main(){
	init();
	int T; cin>>T;
	while(T--){ work(); }
}

听蒋神讲完题解做法后发现,我这个做法就是底层逻辑2333,(所以我前两天的拉格朗日乘子还是白学了giao

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值