Time 优化一个完美数检查到O(sqrt(n))

Time 优化一个完美数检查到O(sqrt(n)),time,time-complexity,pascal,freepascal,asymptotic-complexity,Time,Time Complexity,Pascal,Freepascal,Asymptotic Complexity,程序的一部分是检查输入的数字是否是一个完美的数字。我们应该找到一个在O(sqrt(n))中运行的解决方案。我的程序的其余部分在固定时间内运行,但是这个函数让我很为难 function Perfect(x: integer): boolean; var i: integer; sum: integer=0; begin for i := 1 to x-1 do if (x mod i = 0) then sum := sum + i; if sum = x

程序的一部分是检查输入的数字是否是一个完美的数字。我们应该找到一个在O(sqrt(n))中运行的解决方案。我的程序的其余部分在固定时间内运行,但是这个函数让我很为难

function Perfect(x: integer): boolean;
var
  i: integer;
  sum: integer=0;
begin
  for i := 1 to x-1 do
    if (x mod i = 0) then
      sum := sum + i;
    if sum = x then
      exit(true)
    else
      exit(false);
end;
这在O(n)时间内运行,我需要将其缩短为O(sqrt(n))时间

以下是我提出的选项:

(1) 找到一种方法使for循环从1变为sqrt(x)

(2) 找到一种方法来检查一个不使用for循环的完美数字


有什么建议吗?我很感激任何提示、提示、说明等:)

对于I:=1到x-1,您需要迭代循环,而不是
对于I:=2到trunc(sqrt(x))
。 最大整数除数是
x
,但在寻找完美数时,我们不考虑它。我们将总和增加1(或者用1初始化,而不是0)

代码
如果(x模i=0),那么sum:=sum+i为此可以转换为:

if (x mod i = 0) then
  begin
    sum := sum + i;
    sum := sum + (x div i);
  end;
我们得到了以下代码:

function Perfect(x: integer): boolean;
var
  i: integer;
  sum: integer = 1;
  sqrtx: integer;
begin
  sqrtx := trunc(sqrt(x));
  i := 2;
  while i <= sqrtx do
    begin
    if (x mod i = 0) then
      begin
        sum := sum + i;
        sum := sum + (x div i) // you can also compare i and x div i 
                               //to avoid adding the same number twice 
                               //for example when x = 4  both 2 and 4 div 2 will be added
      end;
    inc(i);
    end;
    if sum = x then
      exit(true)
    else
      exit(false);
end;
函数完美(x:integer):布尔;
变量
i:整数;
总和:整数=1;
sqrtx:整数;
开始
sqrtx:=trunc(sqrt(x));
i:=2;

虽然我知道在整数范围内只有少数(5个已知)完美数。简单地把它们放在一个常量数组中。前面的评论并不完全严肃,但事实上,您是对的:您只需要除以1..sqrt(n)。其余的可以镜像。赋值规则中没有规定输入必须是整数,但我会尝试一下。谢谢。即使在UInt64的范围内,也只有9个(已知的)完美数字。你可以在pascal版本的感谢中找到解决方案,这与我最终所做的非常接近。我还将“I:=2”和“trunc(sqrt(x))”放在循环条件中,以尽可能地保持代码的小。