坚持看似琐碎的算法任务

时间:2014-11-19 22:17:47

标签: algorithm

  

给输入一个正整数n,输出一个列表   连续的正整数,总结起来,将弥补这一点   数字或不可能,如果无法完成。如果有多种可能   anwers,输出任何最少的值。

这是几天前举行的CERC竞赛的一个问题,虽然我可以用一些奇怪的理论来解决它,但我不知道如何优雅地解决它。

我知道2 ^ i形式中没有数字,其中i是非负整数,并且任何奇数都可以以二阶形式的地板(n / 2)+(地板( n / 2)+1)但是当谈到偶数时,我对一些优雅的解决方案一无所知,我听说它可以用一个公式来解决。我考虑将数字除去,直到我们留下奇怪的东西,然后试图将这个奇数的加数放在偶数的中心,或者试图将数字除以中间的奇数但是它没有听起来不对,更不用说优雅了。有些团队在10分钟内解决了这个问题,所以我上面提到的路线几乎肯定是错的,而且我太过于思考它了。

解决这个问题的最佳和最快方法是什么?

2 个答案:

答案 0 :(得分:2)

mn的一组正整数之和为

 n(n + 1)/2 - m(m - 1)/2

(即从1n的数字总和减去从1m - 1的总和

((n^2 - m^2) +(n + m))/2

 (n + m)( n - m + 1)/2

因此,如果您需要为某些x

制作相等的x
2x = (n + m)(n - m + 1)

所以寻找2x的因子,看看哪种模式适合

答案 1 :(得分:0)

Ookay,因为@ Pokechu22对我的团队如何解决它感兴趣(似乎甚至还有一个人,从消息旁边的upvote判断:)),这里就是这样。它有效,它符合时间限制,但要注意它有点扭曲,即使在这几天之后我仍然怀疑它是否仍然记得它是如何工作的:D让我们开始吧。

首先,我们if两个场景 - 如果n为1,则输出Impossible,如果n为奇数,则输出floor(n/2)+(floor(n/2)+1)。现在真正有趣:

我们知道任何偶数必须是至少三个连续整数的和,因为它是两个的和,我们需要两个连续的奇数或两个连续偶数,这是不可能的。因此,我们以下列形式推导出一系列序列及其相应的总和:

Length | Sequence        | Sum
3        1-2-3             6
4        0-1-2-3           6
5        0-1-2-3-4         10
6        IMPOSSIBLE        N/A
7        1-2-3-4-5-6-7     28
8        0-1-2-3-4-5-6-7   28
9        0-1-2-3-4-5-6-7-8 36
10       IMPOSSIBLE        N/A

......等等

事实证明,每个可能的答案序列只是其中之一,向右移动了一些数字。要查找数字是多少,对于上表中的每个元素sum_i,我们会检查n-sum_i是否可以被length_i整除。如果是,我们有我们的解决方案,因为剩下的就是将给定序列移动那么多位置(换句话说,将(n-sum_i)/length_i添加到sequence_i的每个元素)。如果在开头使用带有0的序列,我们还必须记住将其向右移动一个额外的空格(从下一个整数开始)。因此,我们得到一个代码如下:

bool shouldBeShifted = false;
bool foundSolution = false;
long long sum_i = 6, length_i = 3;

while(n - sum_i >= 0)
{
    long long tmp = n - sum_i;
    if(tmp % length_i == 0) {foundSolution = true; break;}

    ++length_i;
    if(tmp % length_i == 0) {foundSolution = true; shouldBeShifted = true; break;}

    sum_i += length_i;
    ++length_i;
    tmp = n - sum_i;
    if(tmp % length_i == 0) {foundSolution = true; break;}

    length_i += 2;
    sum_i = ((3 * length_i) - 3) + sum_i;
    shouldBeShifted = false;
}

如果循环foundSolution结果为true后,我们找到了一个长度为length_i的解决方案,从(n / length_i) - (length_i / 2) + (shouldBeShifted ? 1 : 0)开始:)信不信由你,它确实有效并找到最佳解决方案......:D