题目:一个组数据从0到N(50000)的N个数字依次递增且不重复,现抽掉其中两个数,并把剩下的49998个数字打乱装入int A[]数组中。请在只遍历一次循环且最多只可用到5个变量,找出这2个抽出的数字。
简单答案:
long a=0,b=0;
for(int i=1;i<=50000;i++)
{
a += i;
b += (i*i);
if(i<49998)
{
a -= A[i-1];
b -= (A[i-1]*A[i-1]);
}
}
/*
到此,假设未知数是,x1,x2;上面也是主要算出a,b 的值
即x1+x2 = a;
x1*x1 + x2*x2 = b;
那么可通过数学的求未知数可行:x1*x2 = (a*a-b)/2;
*/
cout<<"x1= " << (sqrt(2*b-a*a)+a)/2 << ", x2="<< (a -(sqrt(2*b-a*a)+a)/2)<<endl;
感谢仁兄:
Qiongzhu
思路:
遍历一次数组,求出这两个数的和a+b 与平方和a*a+b*b
a+b = 1+2+3+4+...+N- sum(A[]); (1)
a*a+b*b = (1*1)+(2*2)+(3*3)+(4*4)+...+(N*N) / sum(A[]*A[]); (2)
假设
m=a+b
n=a*a+b*b
则
a=(m+sqrt((2*n-m*m)))/2
b=(m-sqrt((2*n-m*m)))/2
边界
N < pow(2, 17)
N*N < pow(2, 34) < pow(2, 63)
1+2+3+4+...+N的值为N*(N+1)/2 < pow(2, 33) < pow(2, 63)
(1*1)+(2*2)+(3*3)+(4*4)+...+(N*N) < N*N*N < pow(2, 50) < pow(2, 63)
使用编译器的扩展长整型__int64,可以表示和,以及平方和