测试20210422T1 Sample

在这里插入图片描述

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

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

QQ图片20210422160054

​ 设最优解为 p ∗ p^* p ,那么任意 p a ∗ , p b ∗ p_a^*,p_b^* pa,pb 一定满足 a f ′ ( p a ∗ ) = b f ′ ( p b ∗ ) af'(p_a^*)=bf'(p_b^*) af(pa)=bf(pb) 。这个很好理解,假设 a f ′ ( p a ∗ ) > b f ′ ( p b ∗ ) af'(p_a^*)>bf'(p_b^*) af(pa)>bf(pb) ,则可以让 p a ∗ + x p_a^*+x pa+x p b ∗ − x , ( x → 0 ) p_b^*-x,(x\rightarrow0) pbx,(x0) ,于是 a p a ∗ ( 1 − p a ∗ ) + b p b ∗ ( 1 − p b ∗ ) < a ( p a ∗ + x ) ( 1 − ( p a ∗ + x ) ) + b ( p b ∗ − x ) ( 1 − ( p b ∗ − 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 就不是最优的了。所以画出每一个 y i = i f ′ ( p ) y_i=if'(p) yi=if(p) 的图像

QQ图片20210422160054

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

posted @ 2022-10-10 20:18  缙云山车神  阅读(11)  评论(0编辑  收藏  举报