筛选素数,分解质因数

{首先,说明一个问题,一个数的大于它开方的质因数最多一个;等于的可以两个,即它开方得到的数是质数的话,即为该数;
问题可以这样描述,当一个数筛去小于等于自身开方的数之后就之多只有一个质因数了,详情看程序
不妨反证一下,若有第二个,则仅仅这两个数乘起来就比x大了,所以没有第二个}
program sky;{筛选法求素数,分解质因数}
var
  i,j,l,tot,x:longint;
  xx:array[1..100000,1..2] of longint;
  a:array[1..500000]of longint;
  v:array[1..500000] of boolean;
procedure init;{打素数表,思想为从头筛,找到一个质数就把它所有倍数删去(布尔数组实现),直至没有}
begin
  assign(output,'pr.out');rewrite(output);
  l:=0;
  for i:=2 to 500000 do{500000以内的素数}
    begin
      if not v[i] then
        begin
          inc(tot); a[tot]:=i; j:=2;
          while i*j<=500000 do begin v[i*j]:=true;inc(j); end;
        end;
    end;
//  for i:=1 to tot do writeln(a[i]);
//  close(output);
end;
procedure doing;
begin
  read(x);
  i:=0;  tot:=0;
  while a[i]<sqrt(x) do{虽然x在变,不过这不会导致结果出错,因为div之后就存储起来,问题就变成弄一个更小的数的质因数,之所以不取等号是因为,先判断再运算,举个例子,当x=9时,第一个质数为2,跳过,发现没超,第二个为3,发现可以div,自己模拟吧。。。}
    begin
      inc(i);
      if x mod a[i]=0 then begin inc(tot); xx[tot,1]:=a[i]; end;{xx数组存储读入的x的质因数,第一个域表示质因数,第二个域为该质因数的个数}
      while x mod a[i]=0 do{记录个数。。}
        begin
         inc(xx[tot,2]); x:=x div a[i];
        end;
    end;
  if x<>1 then begin inc(tot); xx[tot,1]:=x; xx[tot,2]:=1; end;{处理边界,x最后还有剩余的话,那么就是那个大于sqrt(x)的数}
  for i:=1 to tot do writeln(xx[i,1],' ',xx[i,2]);
end;

begin
  init;
  doing;
  close(output);
end.

原文地址:https://www.cnblogs.com/skysun/p/2135530.html