1 条题解

  • 0
    @ 2025-8-24 23:07:00

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar yummy
    这个人是时代的眼泪,什么也没有留下

    搬运于2025-08-24 23:07:00,当前版本为作者最后更新于2024-12-18 13:39:47,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    结论

    第一步纯分子 +1+1。从 1x\dfrac{1}{x} 开始,每次:

    • xx 是奇数,则分子和分母都 +1+1
    • xx 是偶数,则分子 +1+1

    这样,每次 xx 都会变成 x/2\lceil x/2 \rceil,总步数为 log2x+1\lceil \log_2 x\rceil+1

    感性理解的缺陷

    一个常见的感性理解是:

    • 由于 log2nn1\dfrac{\log_2 n}{n-1}n=2n=2 时取最大值,因此每次约分约掉 22 的“性价比”是最高的。
    • 约掉相同的 gcd\gcd,约分的时机越早,+1+1 次数越小。

    然而这些感性理解有一些问题,包括但不限于:

    • 完全没有考虑约分后分子不是 11 的情形,如 $\dfrac{1}{5},\dfrac{2}{5},\dfrac 3 5,\dfrac 2 3, \dfrac 1 1$ 这种路径为什么一定不优。
    • 背包问题告诉我们,性价比最大不代表总价值最大。
    • 事实上,如果初始分子不是 11,结论完全不长这样,但是你能写一个类似的“感性理解”出来,说明确实还有逻辑漏洞。

    出题人也给过我一些补丁,但是打上补丁之后,因为无法穷尽所有可能的策略,所以仍然有一些新问题。

    参考证明

    下面的论证均从 1x\dfrac{1}{x} 开始。

    aia_i 为第 ii+1+1 前的分母,bib_i 为第 ii+1+1 前的分子,并且最优方案用了 nn 步。

    根据定义,a1=xa_1=xb1=1b_1=1,且 an=bn=1a_n=b_n=1,并且:

    • 1i<n\forall 1\le i<n,存在 1ki<bi+11\le k_i<b_{i}+1 使得 bi+1=bi+1kib_{i+1}=\dfrac{b_i+1}{k_i}(分子固定 +1+1
    • 此时必有 $\dfrac{a_i}{k_i}\le a_{i+1}\le \dfrac{a_{i}+1 }{k_i}$。

    Lemma i=1n1ki2n2\sum\limits_{i=1}^{n-1} k_i \le 2n-2

    Proof 依题意,bi+1ki=bi+1b_{i+1}k_i = b_i+1,得到 bi+1(ki1)=bibi+1+1b_{i+1}(k_i-1) = b_i-b_{i+1}+1,从而 ki1bibi+1+1k_{i}-1\le b_i-b_{i+1}+1。把 1-1 移项后对两边求和,有 $\sum\limits_{i=1}^{n-1} k_i \le b_1-b_n + (2n-2)=2n-2$。

    Proof of theorem 由数学归纳法,有 x=a1i=1n1kix=a_1 \le \prod\limits_{i=1}^{n-1} k_i。只需证明所有 kik_i 都是 22 的时候,i=1n1ki\prod\limits_{i=1}^{n-1} k_i 最大,就可以证明 nlog2xn\ge \lceil \log_2 x \rceil

    若有的 kik_i 不是 22,由于所有 kik_i 总和是 2n22n-2,则至少存在一对 kp=1,kq>2k_p=1,k_q>2。此时 (kp+1)(kq1)=kpkq+(kqkp1)>kpkq(k_p+1)(k_q-1)=k_pk_q+(k_q-k_p-1) >k_pk_q,从而这个 kik_i 不是最大的。

    由于 2n22n-2 的划分方案数是有限的,因此最大值必然存在。从而,最大值在 kik_i 全是 22 时取到。

    参考代码

    #include<bits/stdc++.h>
    using namespace std;
    const long long Mod=998244353;
    int main(){
    	long long n,ans=1;
    	scanf("%lld",&n);
    	for(int i=0;i<=61;i++){
    		long long l=(1ll<<i)+1,r=min(n,2ll<<i);
    		if(l>n)break;
    		ans=(ans+(r-l+1)%Mod*(i+2))%Mod;
    	}
    	printf("%lld\n",ans);
    	return 0;
    }
    
    • 1

    信息

    ID
    10940
    时间
    1000ms
    内存
    512MiB
    难度
    4
    标签
    递交数
    0
    已通过
    0
    上传者