2022 年上海市大学生程序设计竞赛C. Coffee Overdose

正解应该是推出式子,用 O ( 1 ) O(1) O(1) 的方法求解。

但是由于实在没太看懂,然后在牛客上翻到一个 O ( n ) O(\sqrt{n}) On ) 的做法,理解之后附在下面。

  1. 喝咖啡的时候体力值 u u u 必然满足 u ⩽ C ( C + 1 ) 2 u \leqslant \frac{C(C + 1)}{2} u2C(C+1)

假设在体力值为 u u u 的时候开始喝(一次),那么之后的体力值为: [ u , u , ⋯   , u ⏟ C , u − c − 1 , u − c − 2 , ⋯   , 1 ] [\underbrace{u, u, \cdots, u}_{C}, u - c - 1, u - c - 2, \cdots, 1] [C u,u,,u,uc1,uc2,,1]

对比不喝咖啡,体力值为: [ u , u − 1 , u − 2 , ⋯   , 2 , 1 ] [u, u - 1, u - 2, \cdots, 2, 1] [u,u1,u2,,2,1]

两者做差,为 C − C ( C − 1 ) 2 − u C - \frac{C(C - 1)}{2} - u C2C(C1)u 。为了让该式子非负,则 u ⩽ C ( C + 1 ) 2 u \leqslant \frac{C(C + 1)}{2} u2C(C+1)

  1. 如果从某个时刻开始喝咖啡,则此后喝咖啡是必然不间断的。

如果在第一 次喝咖啡后存在某个时刻体力值为 i i i ,可以喝咖啡却没有喝,则必然可以将体力值为 i i i 之前的第一 次喝咖啡时刻推迟到 i i i 而其他喝咖啡时刻不变,这样调整后总完成度一定会变好。(by官方题解)

  1. 应该从 C C C 的整数倍开始喝

假设在体力值为 u u u 的时候开始喝,那么之后的体力值为: [ u , u , ⋯   , u ⏟ C , u − c − 1 , u − c − 1 , . . . ] [\underbrace{u, u, \cdots, u}_{C}, u - c - 1, u - c - 1, ...] [C u,u,,u,uc1,uc1,...]

假设在体力值为 u − 1 u-1 u1 的时候开始喝,那么之后的体力值为: [ u , u − 1 , u − 1 , ⋯   , u − 1 ⏟ C , u − c − 2 , u − c − 2 , . . . ] [u, \underbrace{u - 1, u - 1, \cdots, u - 1}_{C}, u - c - 2, u - c - 2, ...] [u,C u1,u1,,u1,uc2,uc2,...]

两者做差,差为 C ∗ k − u C*k - u Cku, 则说明当 u u u C C C 的倍数时开始喝最佳。

#include <bits/stdc++.h>
using namespace std;
using ll = long long;

ll t, s, c;
ll k, res, tmp;

int main()
{
    ios::sync_with_stdio(false);
	cin.tie(nullptr); cout.tie(nullptr);
    
    cin >> t;
    
    while(t --)
    {
        cin >> s >> c;
//      直接喝咖啡
        k = s / (c + 1) + 1;
        res = k * c * (s + s % (c + 1)) / 2;
//      s~(j+1) 先不喝,从j开始喝        
        for (ll j = c; j <= min(s, c * (c + 1) / 2); j += c)
        {
            k = j / (c + 1) + 1;
            tmp = (s + j + 1) * (s - j) / 2 + k * c * (j + j % (c + 1)) / 2;
            res = max(res, tmp);
        }
        cout << res << '\n';
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值