Назначение — написать программу на 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
,
Найдем количество полных групп 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
,
образцовый 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 (1/2 + (1/4 + 2 * (т — 1))1/2)
Где R () — это функция, которая округляет число вниз до целого числа.
Но вы после колонны с. Это получается вычитая значение первого члена в этой строке из 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) ;