拿糖果

质因数:质因数(素因数或质因子)在数论里是指能整除给定正整数质数

质数:质数定义为在大于1的自然数中,除了1和它本身以外不再有其他因数

 

目前我的代码测试出来和样例不同,但我觉得我是对的,或者说我还没发现我的错误以及我没有理解对题目的意思吧……

先记录一下

import java.util.Scanner;

public class candy {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner sc=new Scanner(System.in);
		int n=sc.nextInt();
		int p=0;
		int sum=0;
		while(n>=4)
		{for(int i=(int) Math.sqrt(n);i>=1;i--)
		{
			if(n%i==0&&iszhishu(i))
			{
				p=i;
				n=n-p;
				sum=sum+p;
				break;
			}
		}
		}
		System.out.println(sum);
		//  System.out.println(iszhishu(n));
	}

	//判断一个数是不是质数
	private static boolean iszhishu(int i) {
		// TODO Auto-generated method stub
		if(i==1)
			return false;
		else
		{for(int j=2;j<i;j++)
		{
			if(i%j==0)
				return false;
		}

		return true;
		}
	}

}

 

<think>题目要求:将一堆糖果(每个糖果有一个美味程度)分配给两个人(小W和小Z),使得两人得到的美味程度总和的差值最小。实际上,这是一个经典的“最小化分差”问题,也可以看作是一个背包问题:将糖果分成两堆,使得两堆总和的差值最小。 ### 问题分析 设所有糖果的美味程度总和为 $S$,假设小W得到的总和为 $W$,则小Z得到的总和为 $S-W$,他们的差值为 $|2W - S|$。我们的目标是使这个差值最小。因此,问题转化为:在糖果中选取一部分,使得其总和尽可能接近 $S/2$(即背包容量为 $S/2$的背包问题)。 ### 动态规划解法 我们可以使用动态规划来解决。定义状态 $dp[j]$ 表示是否可以凑出总和 $j$($dp[j]$为布尔值)。然后,我们遍历每个糖果,更新状态。最后,我们检查所有不超过 $S/2$ 的 $j$ 中,最大的 $j$ 使得 $dp[j]$ 为真,则最小差值为 $|S - 2j|$。 但是,由于糖果的美味程度可能很大,而糖果数量不大(题目没有给出具体范围,但一般这种问题糖果数量在几百以内),我们可以采用动态规划,但要注意总容量可能很大。实际上,我们关心的只是不超过 $S/2$ 的最大值。 另一种思路:使用01背包的变种,用一维布尔数组记录可能达到的总和。然后从 $S/2$ 开始向下查找第一个能够达到的总和。 ### 算法步骤 1. 计算所有糖果的美味程度总和 $S$。 2. 初始化一个长度为 $S/2+1$ 的布尔数组 $dp$,$dp[0] = true$,其余初始为 false。 3. 遍历每个糖果的美味程度 $a_i$: - 从 $j = S/2$ 到 $a_i$,更新 $dp[j] = dp[j] || dp[j - a_i]$。 4. 从 $j = S/2$ 开始递减,找到第一个 $dp[j]$ 为 true 的 $j$。 5. 最小差值就是 $|S - 2j|$(注意,题目要求的是差值,但题目中要求输出的是最小差值,但问题描述中并没有要求输出具体分配,所以只需要输出最小差值?但是原问题描述是要求分配糖果,但输出的是最小差值?) 然而,问题要求是“使小W和小Z得到的美味程度总和差值最小”,所以输出最小差值即可。 ### 注意 - 由于总和可能很大,我们需要考虑空间和时间复杂度。如果总和很大(比如超过10^6)而糖果数量也很大(比如超过1000),那么动态规划可能不可行。但题目没有给出数据范围,我们假设糖果数量在合理范围内(比如n<=1000,总和不超过1000000)可以使用动态规划。 ### 代码实现 ```cpp #include <iostream> #include <vector> #include <cmath> #include <algorithm> using namespace std; int main() { int n; cin >> n; vector<int> candies(n); int total = 0; for (int i = 0; i < n; i++) { cin >> candies[i]; total += candies[i]; } int half = total / 2; vector<bool> dp(half + 1, false); dp[0] = true; for (int i = 0; i < n; i++) { for (int j = half; j >= candies[i]; j--) { if (dp[j - candies[i]]) { dp[j] = true; } } } int maxSum = 0; for (int j = half; j >= 0; j--) { if (dp[j]) { maxSum = j; break; } } int diff = abs(total - 2 * maxSum); cout << diff << endl; return 0; } ``` ### 示例 输入: ``` 5 1 2 3 4 5 ``` 总和为15,一半为7。能凑出的最接近7的和为7(取1,2,4或者3,4等),则差值为|15-14|=1。 ### 优化 如果总和很大,我们可以使用位运算优化(bitset)来加速布尔数组的操作。例如,当总和较大时,使用bitset可以节省空间和时间。 ### 使用bitset优化 ```cpp #include <iostream> #include <vector> #include <bitset> using namespace std; int main() { int n; cin >> n; vector<int> candies(n); int total = 0; for (int i = 0; i < n; i++) { cin >> candies[i]; total += candies[i]; } int half = total / 2; bitset<1000001> dp; // 假设总和不超过1000000 dp.set(0); // dp[0]=true for (int i = 0; i < n; i++) { dp |= dp << candies[i]; } int maxSum = 0; for (int j = half; j >= 0; j--) { if (dp.test(j)) { maxSum = j; break; } } int diff = abs(total - 2 * maxSum); cout << diff << endl; return 0; } ``` 注意:使用bitset需要知道总和的上限,这里假设上限为1000000,实际中需要根据题目调整。 ### 相关问题 1. 如果要求输出具体的分配方案,如何修改算法? 2. 如果糖果数量非常大(例如n=10000),总和也非常大(例如10^9),如何优化算法? 3. 如果要求最小化差值的分配方案不止一种,如何输出所有方案? 4. 如果糖果的美味程度可以是负数,如何解决? 5. 如果要求两个人分得的糖果数量尽可能相等(即数量差最小),同时美味程度总和差值最小,如何解决? [^1]: 动态规划常用于解决背包问题,包括最小化分差问题。 [^2]: 贪心算法在分配问题中也有应用,但本题不适用贪心。 [^3]: 位运算优化可以加速动态规划的状态转移。</think>### 问题分析 题目要求将一组糖果(每个糖果有特定的美味程度)分配给小W和小Z,使得两人得到的美味程度总和差值最小。这是一个典型的**最小化分差问题**,可以转化为**子集和问题**:寻找一个子集,使其总和尽可能接近所有糖果总美味程度的一半。 ### 数学建模 设所有糖果的美味程度总和为 $S$,小W得到的美味程度总和为 $W$,则小Z得到 $S - W$,差值 $\delta = |2W - S|$。最小化 $\delta$ 等价于找到最接近 $S/2$ 的子集和 $W$。 ### 动态规划解法 使用动态规划解决子集和问题: 1. **状态定义**:$dp[j]$ 表示能否凑出美味程度总和 $j$ 2. **状态转移**:$dp[j] = dp[j] \lor dp[j - a_i]$($a_i$ 为第 $i$ 个糖果的美味程度) 3. **空间优化**:使用一维数组并倒序更新 ### C++ 代码实现 ```cpp #include <iostream> #include <vector> #include <cmath> using namespace std; int main() { int n; cin >> n; // 糖果数量 vector<int> candies(n); int total = 0; // 输入糖果美味程度并计算总和 for (int i = 0; i < n; i++) { cin >> candies[i]; total += candies[i]; } int half = total / 2; vector<bool> dp(half + 1, false); dp[0] = true; // 初始状态:总和为0是可达的 // 动态规划求解可达子集和 for (int i = 0; i < n; i++) { for (int j = half; j >= candies[i]; j--) { if (dp[j - candies[i]]) { dp[j] = true; } } } // 寻找最接近 half 的可达和 int maxSum = 0; for (int j = half; j >= 0; j--) { if (dp[j]) { maxSum = j; break; } } // 计算最小差值 int minDiff = abs(total - 2 * maxSum); cout << "最小差值: " << minDiff << endl; return 0; } ``` ### 算法分析 1. **时间复杂度**:$O(n \cdot S/2)$,其中 $n$ 是糖果数量,$S$ 是总美味程度 2. **空间复杂度**:$O(S/2)$,使用滚动数组优化空间 3. **正确性保证**:动态规划穷举所有可能的子集和,确保找到最优解 ### 示例演示 **输入**: ``` 5 // 5个糖果 1 2 3 4 5 // 美味程度 ``` **处理过程**: 1. 总美味程度 $S = 15$,目标子集和 $S/2 = 7.5$ → 寻找最接近7的子集和 2. 可达子集和:{0,1,2,3,4,5,6,7}(如{1,2,4}=7) 3. 最小差值:$|15 - 2×7| = 1$ **输出**: ``` 最小差值: 1 ``` ### 优化技巧 1. **位集优化**:当 $S$ 较大时,使用 `bitset` 加速状态转移 ```cpp #include <bitset> bitset<MAX_SUM> dp; dp.set(0); for (int candy : candies) dp |= dp << candy; ``` 2. **提前终止**:当找到 $S/2$ 的精确解时可提前结束 ### 相关问题 1. 如果要求输出具体分配方案,如何修改算法?[^1] 2. 当糖果美味程度范围极大($10^9$)时如何优化?[^2] 3. 如果糖果有重量限制(背包问题变种)如何解决?[^3] 4. 如何用贪心算法近似求解大规模问题?[^4] 5. 如果要求两人糖果数量相同,如何修改算法?[^5] [^1]: 需要记录状态转移路径,回溯求解具体分配方案。 [^2]: 考虑使用折半搜索或Meet-in-Middle算法优化时间复杂度。 [^3]: 增加重量维度,转化为二维背包问题。 [^4]: 按美味程度降序排序,轮流分配给当前总和较小的一方。 [^5]: 增加数量约束,转化为带数量限制的子集和问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值