Live2D

Solution -「多校联训」Sample

Description

  Link

  (稍作简化:)对于变量 p1..n,满足 pi[0,1], pi=1 时,求 maxi=1n(pipi2)i

  数据组数 T105n106

Solution

  Lagrange 乘子法的板题,可惜我不会。(

  先忽略 pi[0,1] 的限制,发现这是一个带约数的最优化问题:

max    f=i=1n(pipi2)i,s.t.    g=i=1npi1=0.

考虑在无约束时,i, fpi=0 时能取到 f 的极值,本题由于偏导是一次式,仅有一个解,所以一定是最值。我们尝试将约束 g=0 变成 f 的一个维度,使得当 f 关于 g 的偏导为 0 时恰有 g=0,就能化归为无约束的情况了。具体地,构造

L=f+λg

此时 g 被作为引入变量 λ 的系数,所以当 Lλ=0 时,自然有 g=0。这就是 Lagrange 乘子法。

  回到本题,尝试直接解出 λ,先表示所有 p

Lpi=0=λ+2i4ipipi=λ+2i4i.

代入约束 g=0 中:

i=1nλ+2i4i1=0λ=42nhn.

其中 hn 为调和级数前缀和。注意到直接代入 λ 可能时一段 p 的前缀 <0,所以只好二分钦定一个前缀为 0。假设钦定 p1..t1=0,类似地有

λt=42(nt+1)hnht1.

代入 ft 后简单化简有

ft=(n+t)(nt+1)4λ28(hnht1).

就能直接计算了。单次复杂度是二分的 O(logn)。可以通过单调滑动 t 值预处理做到 O(n)O(1)

Code

/*~Rainybunny~*/

#include <cstdio>

#define rep( i, l, r ) for ( int i = l, rep##i = r; i <= rep##i; ++i )
#define per( i, r, l ) for ( int i = r, per##i = l; i >= per##i; --i )

const int MAXN = 1e6;
double h[MAXN + 5];

inline double calc( const int n, const int t ) {
    double c = n - t + 1, s = 0.5 * ( n + t ) * c,
      lam = ( 4 - 2 * c ) / ( h[n] - h[t - 1] );
    if ( ( lam + 2 * t ) / ( 4 * t ) < 0 ) return -1.;
    return 0.5 * s - 0.125 * lam * lam * ( h[n] - h[t - 1] );
}

int main() {
    freopen( "sample.in", "r", stdin );
    freopen( "sample.out", "w", stdout );

    rep ( i, 1, MAXN ) h[i] = h[i - 1] + 1. / i;

    int T, n; scanf( "%d", &T );
    while ( T-- ) {
        scanf( "%d", &n );
        
        int l = 1, r = n;
        while ( l < r ) {
            int mid = l + r >> 1;
            if ( calc( n, mid ) != -1. ) r = mid;
            else l = mid + 1;
        }
        printf( "%.12f\n", calc( n, l ) );
    }
    return 0;
}

posted @   Rainybunny  阅读(98)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示