1 条题解

  • 0
    @ 2025-8-24 21:25:41

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar ButterflyDew
    life is hard

    搬运于2025-08-24 21:25:40,当前版本为作者最后更新于2018-05-02 21:48:52,作者可能在搬运后再次修改,您可在原文处查看最新版

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

    以下是正文


    • 首先明确第一个问题:这个最小的正整数是多少?

    也许你可以打表看出来,也许不能,但别急,我们有看似靠谱一点的思维方法

    看看样例:6

    可行方案:

    11 22 33;

    11 22 44.

    我们发现,对于方案①,组成3的时候有两种方法(1+2或3),而方案②只有一种。换而言之,3的利用是有浪费的。而不浪费的方案②还可以组成7。

    那么,我们咋让她(每个数)都用好自己呢

    很简单,百合就行了

    联想一下二进制位下的数

    11,1010,1111,100100,101101,110110,111111,10001000...

    可不是嘛,这个2i2^i的每个数利用率可高了

    由此可知,二进制的位数即为这个最小的正整数


    想明白第一问以后,应该给出了一个相对的第二问的思维导向。(当然不绝对哈)

    当每个数的利用率最大的时候,她们能够凑成的最大整数即为她们的和,这点是毋庸置疑的。

    那么,在利用率相对不是那么大的时候呢?

    我们注意到,此时已经有了一个限制条件:已有的最小正整数

    手动模拟一下,确实是仍然成立的。(其实是不太会证啦)

    这时候,我们就把参与量已使用的各数之和凑成的最大整数搞到一起去了

    考虑dp[k]dp[k]代表凑成时kk的方案数。看看这时候还要压哪些信息进去。

    显然,剩下的必要信息还有第ii个数和第ii个数的值jj

    dp[i][j][k]dp[i][j][k]表示已选ii个数,第ii个数为jj,前ii个数和为kk(凑成的最大整数位kk)的时候的方案数

    转移方程 dp[i+1][l][k+l]+=dp[i][j][k];dp[i+1][l][k+l]+=dp[i][j][k];

    其中ll为枚举的下一个填充数

    核心代码:

        dp[1][1][1]=1;
        for(int i=1;i<ans;i++)
            for(int j=i;j<=(1<<(i-1));j++)
                for(int k=i*(i-1)/2;k<(1<<i);k++)
                    for(int l=j+1;l<=k+1;l++)
                        if(l+k<=n)
                            dp[i+1][l][k+l]+=dp[i][j][k];
                        else
                            dp[i+1][l][n]+=dp[i][j][k];
    

    注意j,k,lj,k,l的上下界,都是被已经得到的第一问给约束住了

    当然,也没必要跑这么死,比如kkii开始反而会快一些。

    至于ififelseelse的判断,是为了方便求最后结果的一点点小贪心了。

    • 1

    信息

    ID
    483
    时间
    2000ms
    内存
    125MiB
    难度
    5
    标签
    递交数
    0
    已通过
    0
    上传者