如何以对数时间复杂度生成此序列的第n个数字?

时间:2015-05-23 13:43:00

标签: c algorithm sequence

我有以下问题:

homework problem

点(a)很简单,这是我的解决方案:

#include <stdio.h>
#include <string.h>

#define MAX_DIGITS 1000000

char conjugateDigit(char digit)
{
    if(digit == '1')
        return '2';
    else
        return '1';
}

void conjugateChunk(char* chunk, char* result, int size)
{
    int i = 0;
    for(; i < size; ++i)
    {
        result[i] = conjugateDigit(chunk[i]);
    }
    result[i] = '\0';
}

void displaySequence(int n)
{
    // +1 for '\0'
    char result[MAX_DIGITS + 1];

    // In this variable I store temporally the conjugates at each iteration.
    // Since every component of the sequence is 1/4 the size of the sequence
    // the length of `tmp` will be MAX_DIGITS / 4 + the string terminator.
    char tmp[(MAX_DIGITS / 4) + 1];

    // There I assing the basic value to the sequence
    strcpy(result, "1221");

    // The initial value of k will be 4, since the base sequence has ethe length
    // 4. We can see that at each step the size of the sequence 4 times bigger
    // than the previous one.
    for(int k = 4; k < n; k *= 4)
    {
        // We conjugate the first part of the sequence.
        conjugateChunk(result, tmp, k);

        // We will concatenate the conjugate 2 time to the original sequence
        strcat(result, tmp);
        strcat(result, tmp);

        // Now we conjugate the conjugate in order to get the first part.
        conjugateChunk(tmp, tmp, k);

        strcat(result, tmp);
    }

    for(int i = 0; i < n; ++i)
    {
        printf("%c", result[i]);
    }
    printf("\n");

}

int main()
{
    int n;
    printf("Insert n: ");
    scanf("%d", &n);

    printf("The result is: ");
    displaySequence(n);

    return 0;
}

但是对于b点,我必须以对数时间生成n个数字。我不知道该怎么做。我试图找到该序列的数学属性,但我失败了。你能帮我吗?解决方案本身并不重要,但如何在短时间内解决这类问题。

problem去年(2014年)在布加勒斯特大学数学与计算机科学系的入学考试中获得。

3 个答案:

答案 0 :(得分:1)

有一个简单的编程解决方案,关键是使用递归。

首先确定k的长度超过s_k的最小n,以便在n中存在s_k个数字。根据定义,s_k可以分成4个等长部分。您可以轻松确定第n个符号落入哪个部分,该部分中n个符号的数量是多少---请说明n - 符号整个字符串是n' - 在这一部分内。这部分是s_{k-1}inv(s_{k-1})。在任何情况下,你递归地确定n'中的s_{k-1}符号是什么,然后,如果需要,将其反转。

答案 1 :(得分:1)

假设您将 d_ij 定义为 s_j i 数字的值。

请注意,对于固定的 i d_ij 仅针对足够大的 j 值定义(首先, s_j < / em>不够大。)

现在你应该能够向自己证明以下两点:

  • 一旦 d_ij 为某些 j 定义,它将永远不会随着 j 的增加而改变(提示:归纳)。

  • 对于已修复的 i d i 中定义为 j 对数(提示:如何将 s_j 的长度作为 j 的函数增加?)。

将此项与您解决的第一项相结合,应该会给出结果以及复杂性证据。

答案 2 :(得分:1)

最多4 ^ k的数字用于确定最多4 ^(k + 1)的数字。这表明在基数4中写n。

考虑我们将数字组合在一起的n的二进制扩展,或者等价于我们写0 =(00),1 =(01),2 =(10)和3 =(11)的基数4扩展。

如果第n个数字是1则设f(n)= +1,如果第n个数字是2则设为-1,其中序列从索引0开始,因此f(0)= 1,f(1)= - 1 ,f(2)-1,f(3)= 1。该索引比从1开始用于计算问题中的示例的索引低一个。基于0的第n位是(3-f(n))/ 2。如果将索引开始为1,则第n位为(3-f(n-1))/ 2.

f((00)n) = f(n).
f((01)n) = -f(n).
f((10)n) = -f(n).
f((11)n) = f(n).

你可以使用它们递归地计算f,但由于它是一个反向递归,你也可以迭代地计算f。 f(n)是( - 1)^(n的二进制权重)=( - 1)^(n的二进制数之和)。

请参阅Thue-Morse sequence