在黑板上写下50个数字:1至50,在接下来的49轮操作中,每次做如下操作,选取两个黑板上的数字a和b
擦去,在黑板上写|b-a|,请问最后一次动作之后剩下数字可能是什么?为什么?(不用写代码,不写原因不得分)。
分析 : 1、总和为 s=50×51/2=1275 假设 操作若干次 后剩余一个数字. 2、每次操作相当从总和 s中减去(a+b)-|a-b| ,
即-2b或-2a(a>b和a<b) 3、由上2步可以确定剩余的数据是一个奇数(1<=m<=49) 4、接下来验证是不是每个奇数都可能被剩下:
那我们先把m拿出来(r=s-m),其他经过n操作为0即可。 一样的道理 经n次操作 后 黑板上剩下0。即2(a1+b2+b3.....an)=r
因为s为奇数减去一个奇数m。即r肯定为偶数。 那是求证在除m外的数据中存在和加起来为r/2的情况,如果存在,说明m可以被剩下。
代码:
private static List<Integer> whatLeave(int n) {
List<Integer> leaveNumList = new ArrayList<Integer>();
int sum = n * (n + 1) / 2;
int leavNum = 0;
if (sum % 2 == 0) {//偶数
leavNum = 0;
} else {//奇数
leavNum = 1;
}
for (; leavNum <= n; leavNum += 2) {
if (isBeLeav(n, leavNum, sum)) {
leaveNumList.add(leavNum);
}
}
return leaveNumList;
}
private static boolean isBeLeav(int n, int leavNum, int sum) {
int otherSum = sum - leavNum;//因为1、sum为偶数,leavNum则为偶数,2、sum为奇数,leavNum则为奇数,所以 other肯定为偶数
//因为要保证leavNum被留下,那其他的n-1个数 经若干次操作后只剩下0
//所以存在一下关系:2(a1+b2+b3.....an)=otherSum
int k = otherSum / 2;
return isExistSomeNumSumEqualK(n, leavNum, k);
}
private static boolean isExistSomeNumSumEqualK(int n, int leavNum, int k) {
int sum = 0;
while (n > 0) {
if (n == leavNum) {
n--;
}
if (sum + n == k) {
return true;
} else if (sum + n < k) {
sum = sum + n;
}
n--;
}
return false;
}