<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Hailuo4ever</title><description>My Personal Blog</description><link>https://fuwari.vercel.app/</link><language>zh_CN</language><item><title>第17届蓝桥杯省赛C/C++ B组题解</title><link>https://fuwari.vercel.app/posts/%E8%93%9D%E6%A1%A5%E6%9D%AF2026%E9%A2%98%E8%A7%A3/</link><guid isPermaLink="true">https://fuwari.vercel.app/posts/%E8%93%9D%E6%A1%A5%E6%9D%AF2026%E9%A2%98%E8%A7%A3/</guid><description>个人补题总结的题解</description><pubDate>Fri, 24 Apr 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;A-青春常数&lt;/h2&gt;
&lt;p&gt;除以 2 即可。注意由于 &lt;code&gt;x&lt;/code&gt; 可以取到 0，所以要 &lt;code&gt;+1&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;Code&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;// Problem: Luogu P16232
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P16232
// Time: 2026-04-12 20:29:57
#include &amp;lt;iostream&amp;gt;
using namespace std;

int main()
{
    cout &amp;lt;&amp;lt; &quot;1013101260121012&quot; &amp;lt;&amp;lt; endl;
    return 0;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;B-双碳战略&lt;/h2&gt;
&lt;p&gt;首先考虑打表来观察规律，用一个数组来存储状态，使用 &lt;code&gt;bfs&lt;/code&gt; 来打表，每种状态对应一个数组。&lt;/p&gt;
&lt;p&gt;打表代码如下：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// Problem: Luogu P16233
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P16233
// Time: 2026-04-12 20:32:24
#include &amp;lt;bits/stdc++.h&amp;gt;
using namespace std;

int n;
queue&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt; q;
map&amp;lt;vector&amp;lt;int&amp;gt;, int&amp;gt; mp;

int main()
{
    cin &amp;gt;&amp;gt; n;
    vector&amp;lt;int&amp;gt; s(n);
    q.push(s);
    mp[s] = 0;

    while (q.size())
    {
        auto u = q.front();
        q.pop();

        for (int i = 0; i &amp;lt; n; i++) // 选定任意一个位置
        {
            auto v = u; // 下一个状态
            if (mp[u] % 2 == 0) // 上一次操作的步数是偶数，则当前是奇数步
            {
                for (int j = i; j &amp;lt; n; j++)
                    v[j] ^= 1; // 反转
            }

            else // 上一次操作的步数是奇数，则当前是偶数步
            {
                for (int j = 0; j &amp;lt;= i; j++)
                    v[j] ^= 1; // 反转
            }

            if (!mp.count(v))
            {
                q.push(v);
                mp[v] = mp[u] + 1;
            }
        }
    }

    int res = 0;
    for (auto &amp;amp;[v, dist]: mp)
    {
        for (auto &amp;amp;x: v)
            cerr &amp;lt;&amp;lt; x &amp;lt;&amp;lt; &quot; &quot;;
        cerr &amp;lt;&amp;lt; &quot;步数：&quot; &amp;lt;&amp;lt; dist &amp;lt;&amp;lt; endl;
        res += dist;
    }
    cout &amp;lt;&amp;lt; res &amp;lt;&amp;lt; endl;
    return 0;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;n = 3&lt;/code&gt; 时，结果为 &lt;code&gt;0 1 3 1 2 2 2 1&lt;/code&gt;，总数为 &lt;code&gt;12&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;0 有 1 个，1 有 3 个，2 有 3 个，3 有 1 个&lt;/p&gt;
&lt;p&gt;&lt;code&gt;n = 4&lt;/code&gt; 时，结果为 &lt;code&gt;0 1 3 1 3 4 3 1 2 2 3 2 2 2 2 1&lt;/code&gt;，总数为 &lt;code&gt;32&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;0 有 1 个，1 有 4 个，2 有 6 个，3 有 4 个，4 有 1 个&lt;/p&gt;
&lt;p&gt;观察到规律是杨辉三角，下面考虑每个数对答案的贡献。&lt;/p&gt;
&lt;p&gt;以 &lt;code&gt;n = 4&lt;/code&gt; 的情况为例，显然 &lt;code&gt;1&lt;/code&gt; 的贡献是 &lt;code&gt;1*4&lt;/code&gt;，&lt;code&gt;2&lt;/code&gt; 的贡献是 &lt;code&gt;2*6&lt;/code&gt;，以此类推&lt;/p&gt;
&lt;p&gt;则答案为$\sum_{i=0}^{n} i \cdot C_n^i$，其中 &lt;code&gt;n = 2026&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;根据组合数学恒等式$\sum_{k=0}^{n} k \binom{n}{k} = n \cdot 2^{n-1}$，答案可进一步简化为 $2026 \cdot 2^{2025} \pmod{998244353}$&lt;/p&gt;
&lt;p&gt;最终解得答案为 $792264670$&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// Problem: Luogu P16233
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P16233
// Time: 2026-04-12 20:32:24
#include &amp;lt;bits/stdc++.h&amp;gt;
using namespace std;
const int mod = 998244353;
typedef long long LL;

LL qmi(LL a, LL k)
{
    LL res = 1;
    while (k)
    {
        if (k &amp;amp; 1)
            res = res * a % mod;
        a = a * a % mod;
        k &amp;gt;&amp;gt;= 1;
    }
    return res;
}

void solve()
{
    int n = 2026;
    vector&amp;lt;LL&amp;gt; f(n + 1, 1), g(n + 1, 1);

    for (int i = 1; i &amp;lt;= n; i++)
    {
        f[i] = f[i - 1] * i % mod;
        g[i] = g[i - 1] * qmi(i, mod - 2) % mod;
    }

    int res = 0;
    for (int i = 0; i &amp;lt;= n; i++)
    {
        LL C = f[n] * g[i] % mod * g[n - i] % mod;
        res = (res + C * i % mod) % mod;
    }
    cout &amp;lt;&amp;lt; res &amp;lt;&amp;lt; endl;
}


int main()
{
    // solve();
    LL res = (2026 * qmi(2, 2025) % mod) % mod;
    cout &amp;lt;&amp;lt; res &amp;lt;&amp;lt; endl;
    return 0;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;C-循环右移&lt;/h2&gt;
&lt;p&gt;抽象成一个比大小问题，一个数组满足“循环右移”的条件，当且仅当所有数都相同。&lt;/p&gt;
&lt;h3&gt;Code&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;// Problem: Luogu P16234
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P16234
// Time: 2026-04-12 21:19:54
#include &amp;lt;bits/stdc++.h&amp;gt;
using namespace std;
typedef long long LL;
void solve()
{
    LL n, x, y;
    cin &amp;gt;&amp;gt; n &amp;gt;&amp;gt; x &amp;gt;&amp;gt; y;

    LL res = y - x + 1;
    if (res &amp;lt;= 0)
        cout &amp;lt;&amp;lt; 0 &amp;lt;&amp;lt; &apos;\n&apos;;
    else
        cout &amp;lt;&amp;lt; res &amp;lt;&amp;lt; &apos;\n&apos;;
}

int main()
{
    int T;
    cin &amp;gt;&amp;gt; T;
    while (T--)
        solve();
    return 0;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;D-蓝桥竞技&lt;/h2&gt;
&lt;p&gt;首先发现 &lt;code&gt;sum % 5&lt;/code&gt; 必须等于 &lt;code&gt;0&lt;/code&gt;，且一定要有 &lt;code&gt;sum / 5&lt;/code&gt; 支队伍。&lt;/p&gt;
&lt;p&gt;我们发现，假如一共有 &lt;code&gt;3&lt;/code&gt; 支队伍，那么每个位置上不能超过 &lt;code&gt;3&lt;/code&gt; 个人，否则没办法分配&lt;/p&gt;
&lt;p&gt;则我们得到了&lt;strong&gt;必要条件 1：&lt;/strong&gt;$\sum a_i \bmod 5 = 0$&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;必要条件 2：&lt;/strong&gt;$\forall i,\ a_i \leqslant \frac{\sum a_i}{5}$，也就是说给定数组的最大值不能大过 &lt;code&gt;sum / 5&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;根据&lt;strong&gt;摩尔投票算法&lt;/strong&gt;，可以推导出一个结论：必要条件 1 + 必要条件 2 -&amp;gt; 充要条件&lt;/p&gt;
&lt;h3&gt;Code&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;// Problem: Luogu P16235
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P16235
// Time: 2026-04-12 21:20:41
#include &amp;lt;bits/stdc++.h&amp;gt;
using namespace std;
typedef long long LL;
void solve()
{
    int n;
    cin &amp;gt;&amp;gt; n;
    LL mx = 0, sum = 0;
    for (int i = 0; i &amp;lt; n; i++)
    {
        LL x;
        cin &amp;gt;&amp;gt; x;
        sum += x;
        mx = max(mx, x);
    }

    if (sum % 5 || (sum / 5 &amp;lt; mx))
        cout &amp;lt;&amp;lt; &quot;F&quot; &amp;lt;&amp;lt; endl;
    else
        cout &amp;lt;&amp;lt; &quot;T&quot; &amp;lt;&amp;lt; endl;
}

int main()
{
    int T;
    cin &amp;gt;&amp;gt; T;
    while (T--)
        solve();
    return 0;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;E-LQ 聚合&lt;/h2&gt;
&lt;h3&gt;做法 1-贪心 + 讨论&lt;/h3&gt;
&lt;p&gt;根据贪心，我们把靠前的问号尽可能改成 &lt;code&gt;L&lt;/code&gt;，靠后的问号尽可能改成 &lt;code&gt;Q&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;也就是说，存在一个最优的分界点，在分界点前面的问号都改成 &lt;code&gt;L&lt;/code&gt;，后面都改成 &lt;code&gt;Q&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;字符串总长为 &lt;code&gt;n&lt;/code&gt;，可以$O(n)$的枚举每一个位置作分界点&lt;/p&gt;
&lt;p&gt;下面考虑分界点左右的贡献计算。&lt;/p&gt;
&lt;h4&gt;Code&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;// Problem: Luogu P16236
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P16236
// Time: 2026-04-12 21:43:17
#include &amp;lt;bits/stdc++.h&amp;gt;
using namespace std;
typedef long long LL;

int main()
{
    int n;
    string s;
    cin &amp;gt;&amp;gt; n &amp;gt;&amp;gt; s;

    s = &quot; &quot; + s;
    vector&amp;lt;int&amp;gt; L(n + 1), Q(n + 1), X(n + 1);
    vector&amp;lt;LL&amp;gt; sq(n + 1), sl(n + 2);
    // sq统计左半部分的?Q，sl统计右半部分的L?

    int sum = 0; // 贡献6
    for (int i = 1; i &amp;lt;= n; i++)
    {
        // 预处理区间数量
        L[i] = L[i - 1];
        Q[i] = Q[i - 1];
        X[i] = X[i - 1];
        sq[i] = sq[i - 1];

        if (s[i] == &apos;L&apos;)
            L[i]++;
        else if (s[i] == &apos;Q&apos;)
        {
            Q[i]++;
            sq[i] += X[i];
            sum += L[i];
        }
        else
            X[i]++;
    }

    for (int i = n; i &amp;gt; 0; i--)
    {
        sl[i] = sl[i + 1];
        if (s[i] == &apos;L&apos;)
            sl[i] += (X[n] - X[i]);
    }

    LL res = 0;

    for (int i = 0; i &amp;lt;= n; i++)
    {
        LL add = 0;
        add += 1LL * X[i] * (X[n] - X[i]); // 左问号乘右问号
        add += 1LL * X[i] * (Q[n] - Q[i]); // 左问号乘右Q
        add += 1LL * L[i] * (X[n] - X[i]); // 左L乘左问号
        add += 1LL * sq[i] + sl[i + 1]; // 左L和左？and 右？和右Q
        res = max(res, add);
    }
    cout &amp;lt;&amp;lt; res + sum &amp;lt;&amp;lt; endl;
    return 0;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;做法 2-DP&lt;/h3&gt;
&lt;p&gt;根据题意，对于每个 &lt;code&gt;Q&lt;/code&gt;，它前面有多少个 &lt;code&gt;L&lt;/code&gt;，就做出多少的贡献，所以问题可以转化为：在每个？处决定填 &lt;code&gt;L&lt;/code&gt; 还是填 &lt;code&gt;Q&lt;/code&gt;，使得所有 &lt;code&gt;Q&lt;/code&gt; 前面的 L 总数之和最大。&lt;/p&gt;
&lt;p&gt;我们可以采取简单 DP 的思维，因为 &lt;code&gt;L&lt;/code&gt;、&lt;code&gt;Q&lt;/code&gt; 的选择只会影响后续的值，所以只需要逐步递推，维护三个变量去记录它们在递推中的数量变化即可。&lt;/p&gt;
&lt;p&gt;状态表示（以单变量的形式）：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$f_i$：处理完前$i$个字符后，当前已获得的最大 LQ 聚合数。&lt;/li&gt;
&lt;li&gt;$l$：当前已经确定（包括已经决定填 &lt;code&gt;L&lt;/code&gt;）的 &lt;code&gt;L&lt;/code&gt; 的个数。&lt;/li&gt;
&lt;li&gt;$q$：尚未扫描到的原始 &lt;code&gt;Q&lt;/code&gt; 的数量。&lt;/li&gt;
&lt;li&gt;$r$：尚未扫描到的 &lt;code&gt;?&lt;/code&gt; 的数量。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;状态转移：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;遇到 &lt;code&gt;L&lt;/code&gt; 时：$l = l + 1, f_i = f_{i -1 }$（最大值不变）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;遇到 &lt;code&gt;Q&lt;/code&gt; 时：$q=q-1,f_i=f_{i-1}+l$（当前的 &lt;code&gt;Q&lt;/code&gt; 与前面所有的 &lt;code&gt;L&lt;/code&gt; 形成$l$个新对）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;遇到 &lt;code&gt;?&lt;/code&gt; 时：先令$r=r-1$（&lt;code&gt;?&lt;/code&gt; 被消耗一个），然后比较选择 &lt;code&gt;L&lt;/code&gt; 时未来最多能匹配的 &lt;code&gt;Q&lt;/code&gt; 数量（$r+q$）与当前选择 &lt;code&gt;Q&lt;/code&gt; 时能和先前已有的 &lt;code&gt;L&lt;/code&gt; 能产生的匹配数量（$l$）：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;若$r+q &amp;gt; l$，则当前把 &lt;code&gt;?&lt;/code&gt; 变成 &lt;code&gt;L&lt;/code&gt; 更优，即$l = l + 1, f_i = f_{i -1 }$&lt;/li&gt;
&lt;li&gt;否则，当前把 &lt;code&gt;?&lt;/code&gt; 变成 &lt;code&gt;Q&lt;/code&gt; 更优，即$f_i=f_{i-1}+l$&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Code&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;// Problem: Luogu P16236
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P16236
// Time: 2026-04-16 22:55:44
#include &amp;lt;iostream&amp;gt;
using namespace std;
typedef long long LL;
const int N = 1e5 + 10;
int a[N];
LL f[N];

int main()
{
    int n;
    cin &amp;gt;&amp;gt; n;

    LL l = 0, q = 0, r = 0;

    for (int i = 1; i &amp;lt;= n; i++)
    {
        char x;
        cin &amp;gt;&amp;gt; x;
        if (x == &apos;?&apos;)
            a[i] = 2, r++;
        if (x == &apos;L&apos;)
            a[i] = 0;
        if (x == &apos;Q&apos;)
            a[i] = 1, q++;
    }

    for (int i = 1; i &amp;lt;= n; i++)
    {
        if (a[i] == 0) // L
        {
            l++;
            f[i] = f[i - 1];
        }
        else if (a[i] == 1) // Q
        {
            q--;
            f[i] = f[i - 1] + l;
        }
        else // ?
        {
            r--;
            if (r + q &amp;gt; l)
            {
                l++;
                f[i] = f[i - 1];
            }
            else
            {
                f[i] = f[i - 1] + l;
            }
        }
    }
    cout &amp;lt;&amp;lt; f[n] &amp;lt;&amp;lt; endl;
    return 0;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;F-应急布线&lt;/h2&gt;
&lt;p&gt;考虑使用&lt;strong&gt;并查集&lt;/strong&gt;来解决联通块问题。一开始会形成若干连通块，题目就是求把若干连通块变成一个的最小花费。那么答案一定是连通块的数量减一。&lt;/p&gt;
&lt;p&gt;注意到每次连边会将两个机子连上，一共要连 &lt;code&gt;cnt&lt;/code&gt; 次，&lt;code&gt;n&lt;/code&gt; 台机器总共连 &lt;code&gt;2 * cnt&lt;/code&gt; 次，最好的情况是给 &lt;code&gt;n&lt;/code&gt; 个机器均摊，答案为$\lceil \frac{2cnt}{n} \rceil$&lt;/p&gt;
&lt;h3&gt;Code&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;// Problem: Luogu P16237
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P16237
// Time: 2026-04-14 19:31:29
#include &amp;lt;bits/stdc++.h&amp;gt;
using namespace std;
const int N = 1e5 + 10;

int n, m, cnt;
int p[N];

int find(int x)
{
    if (p[x] != x)
        p[x] = find(p[x]);
    return p[x];
}

int main()
{
    cin &amp;gt;&amp;gt; n &amp;gt;&amp;gt; m;

    for (int i = 1; i &amp;lt;= n; i++)
        p[i] = i;

    while (m--)
    {
        int u, v;
        cin &amp;gt;&amp;gt; u &amp;gt;&amp;gt; v;
        p[find(u)] = find(v);
    }

    for (int i = 1; i &amp;lt;= n; i++)
        if (find(i) == i)
            cnt++;

    cout &amp;lt;&amp;lt; --cnt &amp;lt;&amp;lt; &quot; &quot; &amp;lt;&amp;lt; ceil(2.0 * cnt / n);
    return 0;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;G-理想温度&lt;/h2&gt;
&lt;h3&gt;思路&lt;/h3&gt;
&lt;h4&gt;Step1 - 转化题意&lt;/h4&gt;
&lt;p&gt;首先，定义每个传感器的&lt;strong&gt;初始差值&lt;/strong&gt;$D_i = B_i - A_i$&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;若$D_i = 0$，说明开始时已满足要求。&lt;/li&gt;
&lt;li&gt;如果我们对区间 $[l, r]$ 补偿温度 $k$，那么对于区间内的传感器 $i$，其温度变为 $A_i + k$。它达到理想温度的条件是 $A_i + k = B_i$，即 $k = B_i - A_i = D_i$。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;对于一次操作（区间 $[l, r]$，补偿值 $k$），最终达到理想温度的传感器数量可以分为两部分：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;区间外：&lt;/strong&gt; 原本就满足 $D_i = 0$ 的传感器数量。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;区间内：&lt;/strong&gt; 满足 $D_i = k$ 的传感器数量。&lt;/p&gt;
&lt;p&gt;当我们选择一个区间时，原本在这个区间里的 0 会因为加上 k 而产生损失。&lt;/p&gt;
&lt;p&gt;为了最大化最终数量，我们需要找一个 $k$ 和一个区间 $[l, r]$，使得 &lt;strong&gt;(区间内 k 的个数) - (区间内 0 的个数) 最大&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;设一开始的$D_i$中有$st$个 0，则最终结果为** st + (区间内 k 的个数) - (区间内 0 的个数) **&lt;/p&gt;
&lt;h4&gt;Step2 - 最大子段和 DP 求解&lt;/h4&gt;
&lt;p&gt;我们可以把这个问题看作：对于每一个出现的非零差值 $k$，将数组中等于 $k$ 的位置看作 $+1$，等于 $0$ 的位置看作 $-1$，其余位置看作 $0$。我们要在这个序列中找一个&lt;strong&gt;最大子段和&lt;/strong&gt;。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;预处理前缀和：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;计算所有的$D_i = B_i - A_i$&lt;/li&gt;
&lt;li&gt;统计$D_i=0$的位置，并记录前缀和$s[i]$表示前 $i$个元素中有多少个 0&lt;/li&gt;
&lt;li&gt;用一个哈希表记录每个非零值$k$出现的所有下标&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;贪心计算：&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;对于每一个唯一的非零值 $k$，假设它出现的下标序列为 $p_1, p_2, \dots, p_m$：&lt;/p&gt;
&lt;p&gt;我们要最大化：$(j - i + 1) - (Z[p_j] - Z[p_i - 1])$&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;这里 (j - i + 1) 是区间内 k 的个数，$Z[p_j] - Z[p_i - 1]$ 是区间内 0 的个数。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;可得公式$\text{Gain} = (j - Z[p_j]) - (i - 1 - Z[p_i - 1])$&lt;/p&gt;
&lt;p&gt;对于固定的 $k$，我们只需要遍历下标序列，维护一个 $(i - 1 - Z[p_i - 1])$ 的&lt;strong&gt;最小值&lt;/strong&gt;，即可在 $O(m)$ 时间内算出该 $k$ 值的最大增益。&lt;/p&gt;
&lt;h3&gt;Code&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;// Problem: Luogu P16238
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P16238
// Time: 2026-04-14 23:38:15
#include &amp;lt;bits/stdc++.h&amp;gt;
using namespace std;
typedef long long LL;

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);

    int n;
    cin &amp;gt;&amp;gt; n;

    vector&amp;lt;LL&amp;gt; a(n + 1), b(n + 1), d(n + 1);
    vector&amp;lt;int&amp;gt; s(n + 1, 0);

    int st = 0;

    for (int i = 1; i &amp;lt;= n; i++)
        cin &amp;gt;&amp;gt; a[i];

    for (int i = 1; i &amp;lt;= n; i++)
        cin &amp;gt;&amp;gt; b[i];

    map&amp;lt;LL, vector&amp;lt;int&amp;gt;&amp;gt; mp;

    for (int i = 1; i &amp;lt;= n; i++)
    {
        d[i] = b[i] - a[i];
        s[i] = s[i - 1] + (d[i] == 0 ? 1 : 0);

        if (d[i] == 0)
            st++;
        else
            mp[d[i]].push_back(i);
    }

    int mxres = 0;

    for (auto const &amp;amp;[v, pos]: mp)
    {
        int mnval = 0;

        for (int j = 0; j &amp;lt; pos.size(); j++)
        {
            int k = pos[j];
            int curv = j + 1 - s[k], curu = j - s[k - 1];

            mnval = min(mnval, curu);
            mxres = max(mxres, curv - mnval);
        }
    }

    cout &amp;lt;&amp;lt; st + mxres &amp;lt;&amp;lt; endl;
    return 0;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;H-足球训练&lt;/h2&gt;
&lt;h3&gt;思路&lt;/h3&gt;
&lt;h4&gt;Step1-贪心&lt;/h4&gt;
&lt;p&gt;假设我们给第 $i
$ 个队员分配一天的训练时间，这个分配操作对整体乘积的影响（也就是增幅）为&lt;/p&gt;
&lt;p&gt;$$
\frac{a_i + (k_i + 1)b_i}{a_i + k_i b_i} = 1 + \frac{b_i}{a_i + k_i b_i} = 1 + \frac{1}{\frac{a_i}{b_i} + k_i}
$$&lt;/p&gt;
&lt;p&gt;为了让总乘积最大，我们每次都应该选增幅最大的队员。观察上式，要使增幅最大，就必须让分母最小。&lt;/p&gt;
&lt;p&gt;也就是说，我们按照$\frac{a_i}{b_i} + k_i$从小到大贪心。&lt;/p&gt;
&lt;h3&gt;Step2-模拟（60pts）&lt;/h3&gt;
&lt;p&gt;我们考虑直接模拟，观察到对于 60% 的数据有$m \leqslant 3000$，那么可以用一个优先队列直接模拟。&lt;/p&gt;
&lt;h5&gt;Code&lt;/h5&gt;
&lt;pre&gt;&lt;code&gt;// Problem: Luogu P16239
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P16239
// Time: 2026-04-12 22:42:32
#include &amp;lt;bits/stdc++.h&amp;gt;
using namespace std;
typedef long long LL;
const LL MOD = 998244353;

struct Player
{
    LL a, b;
    LL k; // 已分配的训练天数

    // 增幅 b / (a + kb) 最大的排在堆顶
    bool operator&amp;lt;(const Player &amp;amp;other) const
    {
        // 交叉相乘，代替除法比较
        LL left = b * (other.a + other.k * other.b);
        LL right = other.b * (a + k * b);

        return left &amp;lt; right;
    }
};

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);

    int n;
    LL m;
    cin &amp;gt;&amp;gt; n &amp;gt;&amp;gt; m;

    priority_queue&amp;lt;Player&amp;gt; pq;
    for (int i = 0; i &amp;lt; n; i++)
    {
        LL a, b;
        cin &amp;gt;&amp;gt; a &amp;gt;&amp;gt; b;
        pq.push({a, b, 0}); // 初始天数 k = 0
    }

    for (int i = 0; i &amp;lt; m; i++)
    {
        // 拿出当前增幅最大的队员
        Player top = pq.top();
        pq.pop();

        top.k++;
        pq.push(top);
    }

    LL ans = 1;
    while (!pq.empty())
    {
        Player p = pq.top();
        pq.pop();

        LL strength = (p.a + p.k * p.b) % MOD;
        ans = (ans * strength) % MOD;
    }

    cout &amp;lt;&amp;lt; ans &amp;lt;&amp;lt; &quot;\n&quot;;
    return 0;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Step3-二分答案（100pts）&lt;/h4&gt;
&lt;p&gt;既然我们每次都是挑选 $\frac{a_i}{b_i} + k_i$ 最小的队员不断往上“填平”，这非常像一个“注水”的过程。我们可以二分最终的水面高度（阈值 V）。&lt;/p&gt;
&lt;p&gt;对于一个阈值 V：如果某个队员当前的$\frac{a_i}{b_i} + k_i \leqslant V$，那么他就需要被训练，训练天数为满足$\frac{a_i}{b_i} + k_i - 1 \le V$的最大$k_i$值，即$k_i = \lfloor V - \frac{a_i}{b_i} \rfloor + 1, V \ge \frac{a_i}{b_i}$。&lt;/p&gt;
&lt;p&gt;综上，我们可以二分找到一个最小的阈值 V，使得所有队员需要的训练天数总和$\sum k_i \ge m$&lt;/p&gt;
</content:encoded></item></channel></rss>