Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/visual-studio-2010/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 如何求整数M的最大奇分解?_Algorithm_Language Agnostic - Fatal编程技术网

Algorithm 如何求整数M的最大奇分解?

Algorithm 如何求整数M的最大奇分解?,algorithm,language-agnostic,Algorithm,Language Agnostic,设M为[1;100000000]范围内的整数 M的分解是一组和等于M的唯一整数 如果分解只包含奇数整数,则分解为奇数 若并没有其他M的分解比集合的大小更大,则M的分解是最大的 编写一个函数: int[] maxOddDecomposition(int M) 返回一个最大奇数分解为M的数组。数组中的数字应按升序排列。如果M没有任何奇数分解,则数组应为空。如果有多个正确答案,函数可能返回其中任何一个 例如,M=6有四种分解: 6 = 1 + 2 + 3 = 1 + 5 = 2 + 4

设M为[1;100000000]范围内的整数

M的分解是一组和等于M的唯一整数

如果分解只包含奇数整数,则分解为奇数

若并没有其他M的分解比集合的大小更大,则M的分解是最大的

编写一个函数:

int[] maxOddDecomposition(int M)
返回一个最大奇数分解为M的数组。数组中的数字应按升序排列。如果M没有任何奇数分解,则数组应为空。如果有多个正确答案,函数可能返回其中任何一个

例如,M=6有四种分解:

6 = 1 + 2 + 3
  = 1 + 5
  = 2 + 4
  = 6
只有
1+5
是奇数分解,因此是最大奇数分解。我们应该以数组的形式返回它,使得
数组[0]=1
数组[1]=5

预期最坏情况下的时间和空间复杂度为O(sqrt(M))


我所尝试的:

由于时间复杂度必须是sqrt(M),这让我想起了M算法的朴素分解,我们从1迭代到sqrt(M)。不过,没有出现进一步的想法。只是它必须非常快,只有sqrt(M)步

所以,我做了一些例子。例如,如何找到20的答案?小于20的奇数是多少?1 + 3 + 5 + 7 + ... 我们已经有16个了。我们可以加4,但4是偶数

那么,让我们用(7+4)=11替换7,我们完成了:1+3+5+11。我注意到的是,最初的序列总是有floor(sqrt(M))元素,非常完美。让我们用伪代码对其进行编码:

int len = floor(sqrt(M));
int result[] = new int[len];
int sum = 0;
for (i = 0; i < len - 1; i++) {
    result[i] = 1 + 2*i;
    sum += result[i];
}
result[len - 1] = M - sum;
return result;
int len=楼层(平方米);
int result[]=新的int[len];
整数和=0;
对于(i=0;i
我对M=2做了一个特例,返回一个空数组。我以为就这样,菲尼托

我没有注意到它会被3打断,因为它给出的是
1+2
,而不是
3
。对于5,给出
1+3+1
,而不是
5
。还有更多



你将如何解决这个问题?

这里有一个可行的想法。它需要从构造的贪婪集净删除最多1个

像往常一样构造O(sqrt(M))列表(没有
result[len-1]=M-sum;
)。如果总和不是平方数(即精确):

  • 将下一个最大的奇数相加
  • 取你现在的总数和你的目标数字->N之间的差额

    • 如果N为奇数,请删除相应的数字
    • 如果N是偶数而不是2,则删除小于N的最大奇数,并删除1
    • 如果N为2,则删除刚才添加的倒数第二个数字。这将产生差异0
证明:

  • 如果按顺序添加连续奇数,则列表应尽可能密集-即,不能有更大的列表
  • 此外,差异始终以您在步骤2中添加的奇数为界,因此最多两个数字的净删除始终是奇数或偶数差异的原因
示例:

  • 假设您想要42:construct[1,3,5,7,9,11],add 13=>sum=49,remove 7(无净删除)
  • 您需要39:构造[1,3,5,7,9,11],添加13,删除1和9(净删除1)
  • 您需要38:构造[1,3,5,7,9,11],添加13,删除11(无净删除)

编辑:最后一个案例中的错误由@user1952500纠正,这里是问题的确定性解决方案。假设M={1,3,5,…,2*k-3,2*k-1,r},其中r3(前面案例的推理和处理将在后面介绍):

案例1。如果r是奇数且等于2*k+1:将r添加到列表中,从而给出(k+1)元素的分解

案例2。如果r是偶数:将{(2*k-1),r}替换为{2*k-1+r},给出k元素的分解

案例3。如果r是奇数且不等于2*k+1:将序列{1,2*k-1,r}中的第一个和最后两个元素替换为{2*k+r},给出(k-1)元素的分解

请注意,当输入的形式为n^2+(奇数<2*k+1)时,将出现(k-1)元素的最坏情况

还要注意,如果元素数少于3,则(情况3)将中断。例如,分解5和7。我们将不得不对这些数字进行特殊处理。同样(案例2)将中断3次,并且必须进行特殊处理。对于M=2,没有解。因此,上述限制k>3。其他一切都应该很好

这需要
O(sqrt(M))
步骤

一些C/C++代码:

#include <stdio.h>

int main(int argc, char *argv[])
{
    printf("Enter M:");
    int m = 0;
    scanf("%d", &m);

    int arr[100] = {0};
    printf("The array is:\n");
    switch(m) {
        case 2:
            printf("No solution\n");
            return 0;
        case 1:
        case 3:
        case 5:
        case 7:
            printf("%d\n", m);
            return 0;
    }

    int sum = 0;
    int count = 0;
    for (int i = 1; (sum + i) < m; i+= 2) {
        arr[count++] = i;
        sum += i;
    }
    int start = 0;
    int r = m - sum;
    if (r % 2 == 0) {
        arr[count - 1] += r;
    } else if (r > arr[count - 1]) {
        arr[count++] = r;
    } else {
        start = 1;
        arr[count - 1] += r + 1;
    }

    for (int i = start; i < count; i++) {
        printf("%d\n", arr[i]);
    }

    return 0;
}

我不明白人们为什么要把事情弄得这么复杂。奇数分解就像一个侧面翻转并展开的分区,例如,
n=13

4 4 3 2     =>              =>            =>              7 5 1

x x x x   rotate             x         unfold out      x x x x x x x
x x x x   clockwise     ↖  x  x  ↗      each side       x x x x x
x x x     45 degrees      x  x  x           =>               x
x x                      x  x  x  x 
                          x  x  x
奇分解越大,相应自共轭的“边界平方”越大。所谓“边界正方形”,我指的是左上角的正方形,它在所有大小相似的奇数分解中都是常数。例如,我们可以将
13
写成自共轭
{5,3,3,1,1}
,9单元的“边界平方”将保持不变,并进行相应的奇数分解
{9,3,1}

5 3 3 1 1        =>            9 3 1

x x x x x                x x x x x x x x x
x x x                          x x x
x x x                            x
x
x
要得到具有最大基数的奇数分解,请找到具有偶数余数的最大“边界平方”

例如:

Enter M:24
The array is:
1
3
5
15

Enter M:23
The array is:
3
5
15
M = 24

Bounding square | remainder
1                 23 
4                 20
9                 15
16                8
25...too large

Place the remainder in any diagonally-symmetric way you like. The simplest way might be

xxxx         xxxxxxxx
xxxx   =>    xxxx
xxxx         xxxx
xxxx         xxxx
             x
             x
             x
             x

Decompose: 15,5,3,1
我认为这个Haskell代码输出了所有的可能性:

fm=g[1,3..bestRoot*2-1]余数0[]
式中,根=地板(平方米)
bestRoot=head$dropWhile(\x->odd(m-x^2))[root,root-1..1]
余数=m-最佳根^2
g(x:xs)r上一个res
|null xs=[反向((x+r):res)]

|否则=do r'闻起来像codechef&co。不确定这样一个问题的位置。Sqrt(n)很可能来自于1+3+5+7+。。“总和是二次增长的。”AdamStelmaszczyk笑着说。也许你应该试试某种形式的回报
*Main> f 24
[[1,3,5,15],[1,3,7,13],[1,5,7,11],[3,5,7,9]]

*Main> f 23
[[1,3,19],[1,5,17],[1,7,15],[3,5,15],[3,7,13],[5,7,11]]

*Main> f 38
[[1,3,5,7,9,13]]

*Main> f 37
[[1,3,5,7,21],[1,3,5,9,19],[1,3,7,9,17],[1,5,7,9,15],[3,5,7,9,13]]

*Main> f 100
[[1,3,5,7,9,11,13,15,17,19]]