分配是编写一个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&lt; = n&lt; = 10 ^ 12
因此,当输入更大的数字时,程序输出解决方案所需的时间过长并超过时间限制,即2秒。我现在已经为此工作了5个小时,而且我不知道如何改进这些程序以便它们更快。我还考虑过某个公式,可以帮助确定这个序列中的 n 数字,但我似乎无法在互联网或数学书籍中找到任何关于它的信息。有人能指出我的解决方案吗?我将非常感激。
答案 0 :(得分: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
。
示范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)
第一项工作是写出如下序列:
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)
答案 2 :(得分:0)
使用循环的解决方案。它将输出 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) ;