如何在分形序列中找到第 N 个数字?

How to find the Nth number in a fractal sequence?

本文关键字:数字 分形      更新时间:2023-10-16

任务是编写一个C++程序,该程序接受输入数字n并输出序列中的第n个数字:

1 1 2 1 2 3 1 2 3 4 1 2 3 4 5

1 2 3 4 5 6 ...

这是我到目前为止想出的:

#include <iostream>
using namespace std;
int main()
{
long long n,k=1,result;
cin >> n;
if(n==1){
result=1;
}else{
for(int i=1,j=1;;i=j,j=j+k){
if(n>i&&n<=j){
result=n-i;
break;
}else{
k++;
}
}
}
cout << result << endl;
}

这也是我之前写过的:

#include <iostream>
using namespace std;
int main()
{
long long n,count=0,result;
cin >> n;
for(int i=1;;i++){
for(int j=1;j<=i;j++){
count=count+1;
if(count==n){
result=j;
break;
}
}
if(count>=n){
break;
}
}
cout << result << endl;
}

对于较小的数字,这两种方法都可以正常工作,但问题是我必须遵循约束:


1 <= n <= 10^12

因此,当输入较大的数字时,程序都需要很长时间才能输出解决方案,并且超过了时间限制,即 2 秒。我已经为此工作了 5 个小时,我不知道如何改进这些程序以使它们更快。我还想到了一个可以帮助确定这样一个序列中的第 n个数字的公式,但我似乎在互联网或我的数学书上找不到任何关于它的信息。有人可以指出我的解决方案吗?我将不胜感激。

我们可以按您的顺序对号码进行分组:

(1) (1, 2) (1, 2, 3) ... 

数字总数为

1 + 2 + 3 + ...

后者是算术级数,其总和等于x*(x+1)/2

我们将找到序列中n+1个数字之前的完整组k数。k等于最大整数,使得k*(k+1)/2 <= n.为了找到它,我们将求解二次方程:

x*(x+1)/2 = n 
x^2 + x - 2*n = 0

假设这个等式的正根是x'。我们将其四舍五入到最接近的整数k.如果x' == k(x'是一个整数),那就是答案。否则,答案是n - k*(k+1)/2.

示例性 c++ 实现:

double d = 1 + 8.0 * n;
double x = (-1 + sqrt(d)) / 2;
long long k = floor(x);
long long m = k*(k+1) / 2;
if (m == n) {
return k;
} else {
return n - m;
}

该解决方案具有O(1)时间复杂性。

第一个工作是像这样写出序列:

1
2   3
4   5   6
7   8   9   10

请注意,我们希望将其映射到

1
1   2
1   2   3
1   2   3   4

数字的行位置是通过重新排列算术级数的公式、求解生成的二次、丢弃负根并删除答案的任何小数部分来给出的。数字t出现在整数部分给出的行 r

r = R(1/2 + (1/

4 + 2 * (t - 1))1/2)

其中 R() 是一个将数字向下舍入为整数的函数。

但是你在c列之后。这是从t中减去该行中第一个项的值得出的:

c = t - 1/2 * r * (r - 1)

参考: https://en.wikipedia.org/wiki/Arithmetic_progression

使用循环的解决方案。它将在第n个数字输出。

x = 0 ;
i = 1 ;
do {
x += i ;
if( x == n ) {
cout<< i ;
break ;
}
else if( x > n ) {
cout<< (n - (x-i)) ;
break ;
}
i ++ ;
}while( 1) ;