【VB教学】第十六节 穷举法

http://hi.baidu.com/mfs666/blog/item/658f0a24339fcb34c895591f.html

 

 

一些小的数学方法,也是要会写的。

program maths;
const maxn=100000;
var
i,j,a,b,c,m,n,ct:longint;
p,pt:array[0..maxn] of longint;//存储素数表和质因数表
d:array[0..maxn] of longint ;
f:array[0..maxn] of boolean;
r:array[0..32] of longint;//进制转换时每一位的权
ks:array[0..32] of char;//进制转换时所用的进制数串

function GCD(x,y:longint): longint;//辗转相除法求最大公约数
Var n:longint;
begin
   While x mod y<>0 do begin//当不能整除时
     n:=x; x:=y; y:=n   mod   y//第二个数作为第一个数,余数作为第二个数
   end;
   GCD:=y;
end;

function acm(x,y:longint):longint;//最小公倍数算法,依赖于最大公约数算法
begin
   acm:=x*y div gcd(x,y);
end;

function pe(x:longint):boolean;//判断是否为质数,试除法
var
   i,t:longint;
begin
   t:=trunc(sqrt(x));//试除时除到开根号即可
   for i:=2 to t do
    if x mod i=0 then begin
     pe:=false;
     exit;
    end;
   pe:=true;
end;

procedure shai(x:longint);//筛法求质数表
var
   i,j,t:longint;
   f:array[0..maxn] of boolean;
begin
   fillchar(f,sizeof(f),true);
   t:=trunc(sqrt(x));//同样只处理到根号下
   c:=0;
   for i:=2 to t do
     if f[i] then//如果不是已知的合数
      for j:=2 to (x div i) do//枚举另一个对范围有意义乘数,设为合数
       f[i*j]:=false;
   for i:=2 to x do
    if f[i] then begin
      inc(c);
      p[c]:=i;
    end;
end;

procedure fzy(x:longint);//分解质因数,试除法,依赖筛法所求的质数表
var
   t,j:longint;
begin
t:=x;
shai(x);//筛出小于等于该数的质数
ct:=0;
while t>1 do//如果没有被除尽(变成1)
   for j:=1 to c do//枚举质数
     while t mod p[j]=0 do begin//如果能整除就多次除至出尽
      inc(ct);
      pt[ct]:=p[j];
      t:=t div p[j];
     end;
end;

procedure print(x:longint);//生成排列组合的辅助输出过程
var i:longint;
begin
for i:=1 to x do
   write(d[i]);
writeln;
end;

procedure pl(x,m,n:longint);//字典序生成排列,类似深搜
var i:longint;
begin
for i:=1 to n do//对于本深度,枚举每个数字,如果之前没有使用过,则可以使用
   if f[i] then
    begin
     d[x]:=i; f[i]:=false;
     if x=m then print(m) else pl(x+1,m,n);//如果到达所取的组合深度,则输出,否则处理下一个深度
     f[i]:=true;//回溯
   end;
end;

procedure zh(x,m,n:longint);//组合生成,类似深搜
var i:longint;
begin
for i:=d[x-1]+1 to n-(m-x) do begin//对于每一位,枚举上一位所使用的加1到总数减还剩下的深度的数字
   d[x]:=i;
   if x=m then print(m) else zh(x+1,m,n);
end
end;

function exgcd(a,b:longint;var x,y:longint):longint;//扩展欧几里得算法,不懂,死记。。。
var
t:longint;
begin
if b=0 then begin
   exgcd:=a;
   x:=1;
   y:=0;
end else begin
   exgcd:=exgcd(b,a mod b,x,y);
   t:=x;
   x:=y;
   y:=t-(a div b)*y;
end;
end;

procedure equation(a,b,c:longint;var x0,y0:longint);//依赖于扩展欧几里得算法,求不定方程的一个整数解,即将扩展所求的整数根等倍扩大
var d,x,y:longint;
begin
d:=exgcd(a,b,x,y);
if c mod d>0 then begin
   writeln('no answer');
   halt;
end else begin
x0:=x*(c div d);
y0:=y*(c div d);
end;
end;

function o2t(x:string):longint;//进制转换,其他进制到十进制,按位乘权

var
i,t:longint;
begin
o2t:=0;
for i:=length(x) downto 1 do begin
   if not (x[i] in ['0'..'9']) then
    t:=ord(x[i])-55
   else
    val(x[i],t);
   inc(o2t,t*r[length(x)+1-i]);
end;
end;

function t2o(x,j:longint):string;//十进制到其他进制,整除至商为0
var
i.t,m:longint;

begin
t2o:='';
while t<>0 do begin
    m:=t mod j;
    t2o:=t2o+ks[m];
    t:=t div j;
end;
end;


{procedure gauss;//高斯消元,靠的可能性小,暂时未完成
var
begin

end;
}

begin
   {readln(a,b);
   writeln(gcd(a,b));
   writeln(acm(a,b));
   shai(1000);
   for i:=1 to c do
    writeln(p[i]);
   fillchar(b,sizeof(f),true);
   fillchar(a,sizeof(d),0);
   pl(1,m,n);
   zh(1,m,n);}
   {readln(a);
   fzy(a);
   for i:=1 to ct do
    writeln(pt[i]);}

end.

posted @ 2008-12-11 12:44  jesonpeng  阅读(519)  评论(0编辑  收藏  举报