牛客周赛 Round 115

链接:https://ac.nowcoder.com/acm/contest/119895

A – ICPC Penalty

算法:

模拟。

思路:

无。

关键代码:

void miyan()
{
    string s;
    int n, t;
    cin >> s >> n >> t;

    if (s == "Accepted")
        cout << t + 20 * (n - 1) << endl;
    else
        cout << 0 << endl;
}

B – 小苯的无限数组

算法:

数学。

思路:

无。

关键代码:

void miyan()
{
    ll n, k;
    cin >> n >> k;

    cout << n * (1ll << k) << endl;
}

C – 小苯的真假游戏

算法:

模拟。

思路:

发现答案小于等于 \(2\)。

当钦定 \(a[1]\) 的话是否为真时,即可确定 \(a[n], a[n – 1], ….., a[2]\),最后判断 \(a[2]\) 说的与钦定的值是否相等即可。

关键代码:

void miyan()
{
    int n;
    string s;
    cin >> n >> s;

    auto get = [&](bool flag) -> bool
    {
        bool cur = flag;
        for (int i = n; i >= 1; --i)
        {
            if (cur)
                cur = s[i % n] - '0';
            else
                cur = 1 - (s[i % n] - '0');
        }

        return (cur == flag);
    };

    cout << get(1) + get(0) << endl;
}

D – 小苯的区间选数2.0

算法:

贪心。

思路:

设当前尝试选择的数字为 \(x\),小根堆为 \(q\),贪心策略:

  • 将所有左边界小于等于 \(x\) 的区间都加入至堆中,弹出所有右边界小于 \(x\) 的区间,此时剩余的区间中都包含 \(x\);
  • 执行完上述操作后,如果队列为空,\(mex\) 只能为 \(x\),否则在堆顶的区间中钦定 \(x\),并弹出该区间,然后尝试选择 \(x + 1\);
  • 循环执行该操作,即可确定最终答案。

关键代码:

void miyan()
{
    int n;
    cin >> n;
    vector<pii> a(n);
    for (auto &[x, y] : a)
        cin >> x >> y;

    ranges::sort(a);

    int mex = 0;
    int idx = 0;
    priority_queue<int, vector<int>, greater<>> q;
    while (1)
    {
        while (idx < n && a[idx].first <= mex)
        {
            q.push(a[idx].second);
            ++idx;
        }

        while (q.size() && q.top() < mex)
            q.pop();

        if (q.empty())
            break;

        q.pop();
        ++mex;
    }

    cout << mex << endl;
}

E – 小苯的GCD疑问1.0

算法:

打表。

思路:

打表发现对于任意的 \((l, r, k)\),其最优答案都为 \(gcd = 1\) 的情况。

既选择所有的数字,使用等差数列求和公式计算答案即可。

关键代码:

void miyan()
{
    ll l, r, k;
    cin >> l >> r >> k;

    cout << (l + r) * (r - l + 1ll) / 2ll - r << endl;
}

F – 小苯的GCD疑问2.0

思路1:

打表。

打表发现最优 \(gcd\) 都集中在 \(\frac{n}{k}\) 周围,容易得到思路:尽可能多的枚举 \(\frac{n}{k}\) 周围的数字。

当钦定 \(gcd\) 为 \(d\) 时,那么在 \([1, n]\) 中 \(gcd\) 为 \(d\) 且元素个数最多数字集合是什么?容易想到该集合就是 \(d\) 的倍数的集合,定义 \(cnt\) 为集合大小。

对于 \(cnt\),容易得到其值为 \(\lfloor \frac{n}{d} \rfloor\)。

那么关于 \(d\) 的答案就为:

\(d \times d \times (1 + cnt) \times cnt \div 2\)

此时就可以在 \(O(1)\) 的时间内得到 \(gcd\) 为 \(d\) 的答案。

代码:

void miyan()
{
    ll n, k;
    cin >> n >> k;

    ll ans = 0;
    for (ll d = n / k; d >= max(1ll, n / k - N); --d)
    {
        ll x = n / d;
        ll start = d, end = x * d;
        ll cur = (start + end) * x / 2 * d;

        ans = max(ans, cur);
    }

    cout << ans << endl;
}

思路 2:

整除分块。

枚举 \(gcd\),钦定 \(gcd\) 为 \(d\)。

发现存在 \(d ∈ [l, r]\),使得任意 \(\lfloor \frac{n}{d} \rfloor = \lfloor \frac{n}{l} \rfloor\),那么关于 \([l, r]\) 的答案就为 \(\sum_{d = l}^{r} \lfloor \frac{n}{l} \rfloor\),遂考虑整除分块优化。

void miyan()
{
    ll n, k;
    cin >> n >> k;

    ll ans = 0;
    for (ll l = 1, r; l <= n; l = r + 1)
    {
        ll cnt = n / l;
        if (cnt < k)
            break;
        r = n / cnt;

        ll start = r, end = n / r * r;
        ll cur = (start + end) * cnt / 2 * r;

        ans = max(ans, cur);
    }

    cout << ans << endl;
}
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇