挑战是
给定两个整数x和N.考虑1之间的所有整数 除了x之外,还包括N和。我们想将这些整数划分为 两个不相交的集合(每个整数必须恰好出现在一个集合中) 这些集合中的数字总和是相等的。找一个有效的 分区或确定它不存在。
这是在codechef的编码竞赛中提出来的,我在 C ++ 中为它编写了一个解决方案,但这说错了答案。
这是我的代码
`#include<bits/stdc++.h>
using namespace std;
main(){
int t;
cin>>t;
while(t--){
int n,x;
cin>>x>>n;
long long int sum = (n*(n+1))/2;
sum = sum - x;
if( ( (sum%2)==1 ) || n==2){
cout<<"impossible";
}
else{
sum /= 2;
stack<char> s;
for(int i=n;i>=1;i--){
if(i!=x){
if( (sum-i) >= 0){
s.push('0');
sum = sum - i;
}else
s.push('1');
}else
s.push('2');
}
if(s.top()=='0'){
while(!s.empty()){
cout<<s.top();
s.pop();
}
}else if(s.top()=='1'){
while(!s.empty()){
if(s.top()=='1')
s.top() = '0';
else if(s.top()=='0')
s.top() = '1';
cout<<s.top();
s.pop();
}
}else{
cout<<s.top();
s.pop();
if(s.top()=='0'){
while(!s.empty()){
cout<<s.top();
s.pop();
}
}else{
while(!s.empty()){
if(s.top()=='1')
s.top() = '0';
else if(s.top()=='0')
s.top() = '1';
cout<<s.top();
s.pop();
}
}
}
}
cout<<endl;
}
return 0;
}`
我在这里做的是我首先找到从1到N的所有数字的总和,然后从中删除x,之后如果总和是奇数,那么你就不能将数字分成2个不相交的集合所以打印&#34;不可能&#34;,如果它不是奇数,那么你将它减半,每一组将总和达到这个并开始从N到1的循环并开始从总和中减去i,只要sum-i是&gt; = 0.
对于每个减法,你把它放在一个堆栈中作为&#39; 0&#39;和&#39; 1&#39;以便区分这两个群体。当我变得等于x时,你插入一个&#39; 2&#39;。
最后打印堆栈。在这里打印堆栈可能看起来很复杂,因为首先当我尝试打印它时,结果显示错误的答案,所以我认为它取了i = 1的组作为组&#39; 0&#39;和其他人作为小组&#39; 1&#39;。
答案仍未到来。请任何人告诉我在任何地方是否有错,我不是要求直接代码或答案只是想知道我做错了什么。任何帮助,将不胜感激。谢谢!
答案 0 :(得分:0)
您的算法不适用于所有情况。这是一个反例
取N = 8
和x = 2
; set to partition为S = {1, 3, 4, 5, 6, 7, 8}
,每个分区的总和为17
解决方案是A = {1, 3, 5, 8}, B = {4, 6, 7}
以下是您的算法将尝试解决的问题:
A = {}, B = {}, sum = 17
A = {8}, B = {} sum = 9
A = {8, 7}, B = {} sum = 2
A = {8, 7}, B = {6} sum = 2
...
A = {8, 7}, B = {6, 5, 4, 3} sum = 2
A = {8, 7, 1}, B = {6, 5, 4, 3} sum = 1
正如您所看到的,因为S不包含2,所以您的算法没有提出sum = 0
的解决方案。 只需添加条件显然,这也不起作用。(sum-i) != x
即可使算法正常工作。
这是一个更复杂的解决方案。首先让我们做一些观察。
根据N % 4
,x
必须为奇数或偶数才能存在解。实际上,如果N % 4 = 0
或N % 4 = 3
,则N*(N+1)/2
为偶数,否则为奇数。此外,x
必须具有相同的奇偶校验,因为N*(N+1)/2 - x
必须是偶数。
此外,任何4个连续整数的集合都可以用相等的和分割成两组:一组中的第一个和最后一个整数,另一组中的两个中间整数。
我们来看N = 4
。如果x = 2
,则解决方案为A = {1, 3}, B = {4}
。如果x = 4
,则解决方案为A = {1, 2}, B = {3}
。
将上一个示例与N = 8
和x = 2
结合使用,我们可以删除{5, 6, 7, 8}
,将问题减少到前一个N = 4
和x = 2
。这给了A = {5, 8, 1, 3}, B = {6, 7, 4}
。
我们可以为N % 4 = 0
定义两个基本案例,通过从x-1
降序和N
中移除4个连续整数的序列,可以将任何其他案例简化为基本案例降。基本案例为S = {1, x+1, x+2}
和S = {1, 2, 3}
。
使用相同的流程,我们可以为N % 4 = 1
定义基本案例:基本案例为S = {}
和S = {1, 2, x+1, x+2}
。
对于N % 4 = 2
,过程略有不同:要删除的序列来自2
升序和N
降序。基本案例为S = {2, 3, 4, 5, 6}
,S = {1, x-1, x+1, x+2, x+3}
和S = {1, x-3, x-2, x-1, x+1}
。例如,对于N = 14
和x = 7
,删除{2, 3, 4, 5}
和{11, 12, 13, 14}
会留下S = {1, 6, 8, 9, 10}
,这对应于第二个基本情况。
对于N % 4 = 3
,流程略有不同:要删除的序列来自1
升序,N
降序。基本案例为S = {x-1, x+1, x+2, x+3, x+4, x+5}
,S = {x-3, x-2, x-1, x+1, x+2, x+3}
和S = {x-5, x-4, x-3, x-2, x-1, x+1}
。
以下是快速摘要。
N % 4 = 0
:
从x-1
降序和N
降序删除序列,直至下列其中一项
S = {1, x+1, x+2}
; A = {1, x+1}, B = {x+2}
。
S = {1, 2, 3}
; A = {1, 2}, B = {3}
。
N % 4 = 1
:
从x-1
降序和N
降序删除序列,直至下列其中一项
S = {}
; A = {}, B = {}
。
S = {1, 2, x+1, x+2}
; A = {1, x+2}, B = {2, x+1}
。
N % 4 = 2
:
从2
升序和N
降序删除序列,直到下列之一
S = {2, 3, 4, 5, 6}
; A = {2, 3, 5}, B = {4, 6}
。
S = {1, x-1, x+1, x+2, x+3}
; A = {1, x-1, x+3}, B = {x+1, x+2}
。
S = {1, x-3, x-2, x-1, x+1}
; A = {1, x-2, x-1}, B = {x-3, x+1}
。
N % 4 = 3
:
从1
升序和N
降序删除序列,直到下列之一
S = {x-1, x+1, x+2, x+3, x+4, x+5}
; A = {x-1, x+3, x+5}, B = {x+1, x+2, x+4}
。
S = {x-3, x-2, x-1, x+1, x+2, x+3}
; A = {x-3, x+1, x+2}, B = {x-2, x-1, x+3}
。
S = {x-5, x-4, x-3, x-2, x-1, x+1}
; A = {x-5, x-3, x+1}, B = {x-4, x-2, x-1}
。