Как найти N-е число в фрактальной последовательности?

Назначение — написать программу на 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Это число в такой последовательности, но я не могу найти что-либо об этом в Интернете или в своих книгах по математике. Может ли кто-нибудь указать мне на решение? Я был бы очень признателен.

3

Решение

Мы можем сгруппировать номера в вашей последовательности:

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

Общее количество номеров

1 + 2 + 3 + ...

Последний является арифметической прогрессией, его сумма равна x*(x+1)/2,

Найдем количество полных групп k что идти раньше n+1-й номер в последовательности. 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,

образцовый реализация:

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) сложность времени.

3

Другие решения

Первая задача — выписать последовательность следующим образом:

1
2   3
4   5   6
7   8   9   10

И обратите внимание, что мы хотим сопоставить это с

1
1   2
1   2   3
1   2   3   4

Положение строки числа определяется перестановкой формулы для арифметической прогрессии, решением полученного квадратичного, отбрасыванием отрицательного корня и удалением любой дробной части ответа. Число T появляется в ряду р дается целой частью числа

r = R (1/2 + (1/4 + 2 * (т — 1))1/2)

Где R () — это функция, которая округляет число вниз до целого числа.

Но вы после колонны с. Это получается вычитая значение первого члена в этой строке из T:

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

Ссылка: https://en.wikipedia.org/wiki/Arithmetic_progression

2

Решение с использованием цикла. Это будет номер на 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) ;
0
По вопросам рекламы [email protected]