1 条题解

  • 0
    @ 2025-8-24 21:44:22

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar 妖怪i
    **

    搬运于2025-08-24 21:44:22,当前版本为作者最后更新于2018-10-05 16:27:03,作者可能在搬运后再次修改,您可在原文处查看最新版

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

    以下是正文


    此题一共有两个问题:

    1. 求金币分为两份的最小差值。
    2. 求分为最小差值时的方案数。

    分步解答这两个问题。

    第一个:

    求两份金币的最小差值,那么我们很自然的想到,当两份金币相同时,差值最小。 那么题目就可以转化为,金币的价值最多能达到金币总价值的一半的多少。那么就是01背包了。

    第二个:

    直接求出第一问的金币价值的方案数即可。

    下面贴下代码:

    
    #include<bits/stdc++.h>
    #define mod 1000000
    using namespace std;
    int n,a[350],tot,sum,f[500005];
    long long dp[500005];
    inline int read()
    {
    	int x=0,f=1;char c=getchar();
    	while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
    	while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    	return x*f;
    }
    int main()
    {
    	n=read();
    	for(int i=1;i<=n;i++)
    		a[i]=read(),sum+=a[i];
    	tot=sum;
    	sum/=2;
    	for(int i=1;i<=n;i++)
    		for(int j=sum;j>=a[i];j--)
    			f[j]=max(f[j],f[j-a[i]]+a[i]);
    	printf("%d\n",tot-2*f[sum]);
    	dp[0]=1;
    	for(int i=1;i<=n;i++)
    		for(int j=tot;j>=a[i];j--)
    			dp[j]=(dp[j]+dp[j-a[i]])%mod;
    	printf("%lld",dp[f[sum]]);
    	return 0;
    }
    
    
    • 1

    信息

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