2022牛客多校第二场的J -- 三分做法

赛时百度了线性回归的公式抄过去了,但是听说三分也能做,于是来写一下三分的做法。
三分的值是公差d,想要求出方差,还差个首项。代入d到式子里去,然后展开一下,发现是个二次函数,这样就能确定最优的首项a1的值是多少了。
然后随便写了写,结果被卡精度了。。。。wa了好多发。。
于是细细优化了一下推的式子,能用int的都用int了,然后尽量减少除法的使用次数。

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1e6 + 5, mod = 1e9 + 7;
int a[N];
int n;
int sum;
double f(double d)
{
    double ret = 0;
    double a1 = -(n - 1) * 1.0 / 2 * d + sum * 1.0 / n;
    for (int i = 1; i <= n; i++)
    {
        double x = a1 + (i - 1) * d;
        ret += (a[i] - x) * (a[i] - x);
    }
    return ret;
}
void solve()
{
    cin >> n;
    sum = 0;
    for (int i = 1; i <= n; i++)
    {
        scanf("%lld", &a[i]);
        sum += a[i];
    }
    double l = -1e9, r = 1e9;
    int k = 100;
    while(k--)
    {
        double lmid = l + (r - l) / 3;
        double rmid = l + (r - l) / 3 * 2;
        double fl = f(lmid);
        double fr = f(rmid);
        if (fl < fr) r = rmid;
        else l = lmid;
    }
    // cout << l << " " << r << "\n";
    printf("%.15lf\n", f(l));
}
signed main()
{
    // ios::sync_with_stdio(0);
    // cin.tie(0);
    int tt = 1;
    cin >> tt;
    while (tt--) solve();
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值