zoukankan      html  css  js  c++  java
  • 常用数论算法

    1.求两数的最大公约数
    function  gcd(a,b:integer):integer;
      begin 
        if b=0 then gcd:=a
          else gcd:=gcd (b,a mod b);
      end ;
    
    2.求两数的最小公倍数
    function  lcm(a,b:integer):integer;
      begin
        if a<b then swap(a,b);
        lcm:=a;
        while lcm mod b>0 do inc(lcm,a);
      end;
    或者利用 最小公倍数=a*b/最大公约数
    
    3.素数的求法
     1.小范围内判断一个数是否为质数:
      function prime (n: integer): Boolean;
        var I: integer;
        begin
          for I:=2 to trunc(sqrt(n)) do
            if n mod I=0 then begin 
       prime:=false; exit;
    end;
          prime:=true;
        end;
    
    2.判断longint范围内的数是否为素数(包含求50000以内的素数表):
     procedure getprime;
     var 
     i,j:longint;
     p:array[1..50000] of boolean;
     begin
      fillchar(p,sizeof(p),true);
      p[1]:=false;
      i:=2;
      while i<50000 do begin
        if p[i] then begin
          j:=i*2;
          while j<50000 do begin
            p[j]:=false;
            inc(j,i);
          end;
         end;
         inc(i);
       end;
       l:=0;
       for i:=1 to 50000 do
         if p[i] then begin
           inc(l);pr[l]:=i;
        end;
    end;{getprime}
    
    begin
    for i:=1 to pnum do
     if sqr(p[i])<=x 
     then begin
          if x mod p[i]=0 then
           begin
            IsPrime:=false;
            exit;
           end;
          end 
     else begin
          IsPrime:=true;
          exit;
          end;
    IsPrime:=true;
    end;{prime}
    
    3.利用随即函数判断longint范围内的数是否为素数
    function f(a,b,n:longint):longint;  //求a^b mod n
    var d,t:int64;
    begin
     d:=1;t:=a;
     while b>0 do
      begin
        if t=1 then
          begin
            f:=d;exit;
          end;
        if b mod 2 =1 then d:=d*t mod n;
        b:=b div 2;
        t:=t*t mod n;
      end;
     f:=d
    end;
    function judge(n:longint):boolean;  //判断n是否为素数  n在longint范围内
    var k:integer; bool:boolean; a:longint;
    begin
      randomize;
      bool:=true;
      for k:=1 to 3 do  //适量调整k的大小
        begin
          a:=random(n-2)+1;
          if (f(a,n-1,n) <> 1) then
            begin
              bool:=false;
              exit;    //不是 则退出该子程序 使用break则只退出if循环而不退出子judge函数的运算过程
            end;
        end;
      if bool then  judge:=true          //n 是素数
          else judge:=false;             //n 不是素数 ;
    end;  
    
    4.求前n个素数:
    
    program BasicMath_Prime;
    const
    maxn=1000;
    var
    pnum,n:longint; 
    p:array[1..maxn] of longint;
    function IsPrime(x:longint):boolean;
    var i:integer;
    begin
    for i:=1 to pnum do
     if sqr(p[i])<=x then
      begin
       if x mod p[i]=0 then
         begin
          IsPrime:=false;
           exit;
         end;
     end 
    
     else
      begin
       IsPrime:=true;
       exit;
     end;
    IsPrime:=true;
    end;
    procedure main;
    var x:longint;
    begin
    pnum:=0;
    x:=1;
    while(pnum<n) do
    begin
     inc(x);
     if IsPrime(x) then
      begin
       inc(pnum);
       p[pnum]:=x;
      end;
    end;
    
    end;
    procedure out;
    var i,t:integer;
    begin
    for i:=1 to n do
     begin
    
     write(p[i]:5);t:=t+1;
    
     if t mod 10=0 then writeln;
    
     end;
    end;
    begin
    readln(n);
    
    main;
    out;
    end.
    
    5.求不大于n的所有素数
    
    program sushu3;
    const maxn=10000;
    var
    i,k,n:integer;
    a:array[1..maxn] of integer;
    begin
      readln(n);
      for i:=1 to n do a[i]:=i;
        a[1]:=0;
      i:=2;
      while i<n do
        begin
          k:=2*i;
          while k<=n do
            begin
              a[k]:=0;
              k:=k+i;
            end;
          i:=i+1;
          while (a[i]=0) and (i<n) do i:=i+1;
        end;
      k:=0;
      for i:=1 to n do
       if a[i]<>0  then
           begin
             write(a[i]:5); k:=k+1;
             if k mod 10 =0 then writeln;
           end
    end.
    
    6.将整数分解质因数的积
    
    program BasicMath_PolynomialFactors;
    const
    maxp=1000;
    var
    pnum,n:longint;
    num,p:array[1..maxp] of longint;
    
    procedure main;
    var x:longint;
    begin
     fillchar(num,sizeof(num),0);
     fillchar(p,sizeof(p),0);
     pnum:=0;
     x:=1;
     while(n>1) do
      begin
      inc(x);
      if n mod x=0 then
        begin
         inc(pnum);
         p[pnum]:=x;
         while(n mod x=0) do
           begin
            n:=n div x;
            inc(num[pnum]);
          end;
       end;
     end;
    end;
    
    procedure out;
    var j,i:integer;
    begin
      for i:=1 to pnum do
      for j:=1 to num[i] do
        write(p[i]:5);
      writeln;
    end;
    
    begin
      main;
      out;
    end.
    
    
    
    6  排列组合
    
    (一) 排列数
    
    [算法描述]
    排列数公式
    
    [源程序]
    function A(m,n:integer):integer;
    var
      ans,i:integer;
    begin
      ans:=1;
      for i:=1 to m do
      begin
        ans:=ans*n;
        n:=n-1;
      end;
      A:=ans;
    end;
    
    (二) 组合数
    
    [算法描述]
    组合数公式
    
    [源程序]
    function C(m,n:integer):integer;
    var
      ans,i:integer;
    begin
      ans:=1;
      for i:=1 to m do
      begin
        ans:=ans*n;
        n:=n-1;
      end;
      for i:=1 to m do ans:=ans/i;
      C:=ans;
    end;
    
    (三) 全排列算法
    
    [算法描述]
    1.1,2……N依次赋给a[1]至a[n],输出第一种排列;
    2.构造下一种全排列,分四步完成:
    (1) i的初值为1,在a[1]至a[n]中搜索找出相应的i,使i是a[k]>a[k-1]的k中最大的,即i=max{k|a[k]>a[k-1],k=2,3…n};
    (2) 在a[x]至a[n]中搜索找出相应的j,使j是a[k]>a[i-1]的k中最大的,即j=max{k|a[k]>a[i-1],k=i,i+1…n};
    (3) 交换a[i-1]与a[j]形成新的序列;
    (4) 对新的序列从 a[i+1]……a[n]进行逆序处理,输出相应序列.
    3.重复2直到i=1时结束
    
    [源代码]:
    program quanpailie;
      const maxn=20;
      type arrayt=array[1..maxn]of integer;
      var i,n,temp:integer;
    procedure inverse(var num:arrayt;x:integer);   //对num[x]~num[n]作逆序处理
    var
      numt:arrayt;
      i:integer;
    begin
      for i:=1 to n do
        numt[i]:=num[i];
      for i:=0 to n-x do
        num[x+i]:=numt[n-i];
    end;
    procedure arrange(n:integer);
    var
      num:arrayt;
      i,x,y:byte; temp:integer;
    begin
      num[0]:=0;
      for i:=1 to n do
      begin
        num[i]:=i;
        write(num[i],' ');
      end;
      writeln;
      repeat
        for i:=1 to n do
          if num[i]>num[i-1] then x:=i;
        for i:=x to n do
          if num[i]>num[x-1] then y:=i;
        if x>1 then
        begin
           temp:=num[x-1];num[x-1]:=num[y];num[y]:=temp;
          inverse(num,x);  //对num[x]~num[n]作逆序处理
          for i:=1 to n do write(num[i],' ');  //输出当前序列
          writeln;
        end;
      until x=1;
    end;
    begin {main}
      assign(input,'input.dat'); reset(input);
      assign(output,'output.dat');rewrite(output);
      readln(n);
      arrange(n);
      close(input);close(output);
    end.    
    
    
    7  进制转换
    
    (一) 十进制转N进制
    
    [算法描述]
    辗转相除法.
    
    [源程序]
    function int_to_n(x:cardinal; n:byte):string;
    var
      a:array[1..255] of byte;
      ans:string;
      count,i:byte;
    begin
      ans:='';
      count:=0;
      if x=0 then ans:='0';
      while x>0 do
      begin
        count:=count+1;
        a[count]:=x mod n;
        x:=x div n;
      end;
      for i:=count downto 1 do
        if a[i]<10 then ans:=ans+chr(ord('0')+a[i])
        else ans:=ans+chr(ord('a')-10+a[i]);
      int_to_n:=ans;
    end;
    
    (二) N进制转十进制
    
    [算法描述]
    加权.
    
    [源程序]
    function n_to_int(x:string; n:byte):cardinal;
    var
      a:array[1..255] of byte;
      ans,y:cardinal;
      count,i,j:byte;
    begin
      ans:=0;
      for i:=1 to length(x) do
        if x[i] in ['0'..'9'] then a[i]:=ord(x[i])-ord('0')
        else a[i]:=ord(x[i])-ord('a')+10;
      count:=0;
      for i:=length(x) downto 1 do
      begin
        y:=1;
        for j:=1 to count do y:=y*n;
        count:=count+1;
        ans:=ans+y*a[i];
      end;
      n_to_int:=ans;
    end;    
    (三) 八进制数或十六进制数转换为二进制数,二进制数转换成八进制数和十六进制数的通用程序(仅在整数范围)。如:
    输入一个数m : ABC
    输入此数的进制n : 16
    输出:
    ABC(16)=101010111100(2)
    又如输入一个数m : 101010111100
    输入此数的进制n : 2
    输出:
    101010111100(2)=ABC(16)=5274(8)
    
    【程序清单】
    PROGRAM P12_5b;
    CONST s0=['0'..'9','A'..'F'];
          c:ARRAY [0..15] OF STRING[4]=('0000','0001','0010','0011','0100','0101',
            '0110','0111','1000','1001','1010','1011','1100','1101','1110','1111');
          c0:ARRAY [1..7] OF STRING=('1','10','11','100','101','110','111');
    VAR i,j,k,n,l:Integer;          f:Boolean;
        s,s1,ss:STRING;             ch:Char;
    BEGIN
      assign(input,'input.dat'); reset(input);
      assign(output,'output.dat');rewrite(output);
      ss:='0123456789ABCDEF';
      Write('Input a string : '); Readln(s);    {'输入一个数串}
      REPEAT
        Write('Input a number : '); Readln(n)   {'输入一个此数串进制 }
      UNTIL n IN [2,8,16];
      l:=Length(s); i:=1; f:=True;
      WHILE (i<=l) AND f DO BEGIN               {'检测数串}
        ch:=Upcase(s[i]); Write(ch);
        IF n=16 THEN IF NOT(ch IN s0) THEN f:=False; {'如f为假输出出错信息}
        IF n=8 THEN IF NOT(ch IN ['0'..'7']) THEN f:=False;
        IF n=2 THEN IF NOT(ch IN ['0','1']) THEN f:=False;
        i:=i+1;
      END;
      Write('(',n,') = ');
      IF NOT f THEN BEGIN Writeln('Data Error !'); Readln; Exit END;
      CASE n OF                                 {'分情况处理}
       2:BEGIN                                  {'输入的是二进制数 }
        i:=1; j:=l MOD 4;                       {'按每四位分,取余数j}
        WHILE i<l DO BEGIN                      {'用当循环来处理}
          s1:=Copy(s,i,j);                      {'取出子串}
    IF j<4
    THEN             {'头一个子串因前面没有无用的0的,转换时分别处理 }
    FOR k:=1 TO 7 DO IF s1=c0[k] THEN Write(k) ELSE
            ELSE                    {'以后的子串每四位对应一个十六进制数}
    FOR k:=0 TO 15 DO IF s1=c[k] THEN Write(ss[k+1]);
          i:=i+j; j:=4;             {'除头一个子串外,以后按每四位截取}
        END; Write('(',16,') = ');  {'十六进制数输出结束 }
        i:=1; j:=l MOD 3;                       {'按每三位分, 取余数j }
        WHILE i<l DO BEGIN
          s1:=Copy(s,i,j);
    IF j<3                {'头一个子串因前面没有无用的0,转换时分别处理 }
    THEN FOR k:=1 TO 7 DO IF s1=c0[k] THEN Write(k) ELSE
            ELSE FOR k:=0 TO 7 DO IF s1=Copy(c[k],2,4) THEN Write(ss[k+1]);
          i:=i+j; j:=3;             {'除头一个子串外,以后按每三位截取}
        END; Writeln('(',8,')');    {'八进制数输出结束}
        END;
    8,16:                                     {'输入的是八或十六进制数}
        FOR i:=1 TO l DO BEGIN
          ch:=Upcase(s[i]); j:=Ord(ch)-48;    {'先转成大写,再转成对应的数}
          IF ch IN ['A'..'F'] THEN j:=j-7;
    IF i=1               {'头一个数转换成二进制数,前面无用的0不输出}
            THEN IF ch IN ['1'..'7'] THEN Write(c0[j])
                                     ELSE Write(c[j])
            ELSE IF n=16 THEN Write(c[j])           {'转成十六进制数}
                         ELSE Write(Copy(c[j],2,4)) {'转成八进制数}
          END
        END;
      IF n IN [8,16] THEN Writeln('(',2,')');
      close(input);close(output);
    END.
    (四) 不同进制数之间实数转换的通用程序。
    输入n进制的数m与要转换的p进制的输出。
    如:
    输入一个数m : ABC.CBA
    输入此数的进制n : 16
    输入要转换成的数的进制p : 2
    输出:
    ABC.ABC(16)=101010111100.11001011101(2)
        【程序清单】
    PROGRAM P12_5A;
    TYPE ss=STRING[30];
    VAR m,m1,a,s:ss;
        m0,n,p,i,j,t,s1,x:Integer;      mm,d:LongInt;
    mr:Real;
    PROCEDURE Zhuan(ch:Char);         {过程—数字符转换成数}
      BEGIN
        j:=Ord(ch)-48;                     {数字符转换成数}
        IF ch IN ['A'..'F'] THEN j:=j-7;   {数字符转换成数}
        IF (j<0) AND (j>=n) THEN           {出界输出出错信息,程序终止}
          BEGIN Writeln('Data errer !'); Readln; EXIT END;
      END;
    PROCEDURE Xiao(m:ss);              {过程—小数部分的转换}
      BEGIN
        mr:=0; m0:=Length(m); t:=n;    {初始化}
        IF n=10 THEN Val(m,mr,t) ELSE  {如是十进制数,就直接把数串转换成数} 
    FOR i:=2 TO m0 DO BEGIN      {否则把m,先转换成十进制小数,m[1]是小数点}
      Zhuan(m[i]);               {调用字符转为数的过程}
            mr:=mr+j/t; t:=t*n         {按权一一展开,累加到mr中}
          END;
        m:='.';                        {再把mr转换成p进制的数串}
        WHILE mr>0.00001 DO BEGIN      {精度要求5位小数}
          mr:=mr*p; x:=Trunc(mr);      {用乘p取整法,取出一位整数}
          m:=m+s[x+1]; mr:=mr-x;       {按顺序一一连入m中}
        END;
        Write(m)                       {输出p进制的数串m}
      END;
    BEGIN
    s:='0123456789ABCDEF';              {s字符串用以对应数制用}
    Write('Input m : '); Readln(m);     {输入原数}
    Write('Input n : '); Readln(n);     {输入原数的进制}
    Write('Input p : '); Readln(p);     {输入要转换成的数的进制}
    m0:=Length(m);
    FOR i:=1 TO m0 DO m[i]:=Upcase(m[i]);{转成大写}
    Write(m,'(',n,') = ');               {输出要转换的原数及其进制}
    x:=Pos('.',m);                       {找出小数点的位置。如没有小数点x为0}
    IF x<>0                              {如有小数部分,就把小数(m1)与整数(m)分离}
      THEN BEGIN m1:=Copy(m,x,m0+1-x); m:=Copy(m,1,x-1) END;
    t:=1; mm:=0; m0:=Length(m);          {先做整数部分的转换}
    IF n<>10 THEN                        {把数串m转换成十进制数mm}
      FOR i:=m0 DOWNTO 1 DO BEGIN
    Zhuan(m[i]);                     {调用字符转为数的过程}
        mm:=mm+j*t; t:=t*n               {按权一一展开,累加到mm中}
      END
    ELSE Val(m,mm,t);                    {如是十进制就直接把数串转成数}
    IF p<>10 THEN BEGIN                  {再把mm转换成p进制的数串}
      m:='';
      WHILE mm>0 DO BEGIN                {反序累加到m中}
        m:=s[mm MOD p+1]+m; mm:=mm DIV p END;
      END
    ELSE Str(mm,m);                    {如mm是十进制数就直接转成数}
    IF m<>'0' THEN Write(m);           {先输出整数部分转换的结果}
    IF x<>0 THEN Xiao(m1);             {如有小数部分,就调用过程Xiao}
    Writeln('(', p,')'); Readln;        {最后输出要转换成的数制信息}
    END.
                                 


                                

  • 相关阅读:
    js Validate
    JS
    JS 回车提交,兼容IE、火狐、Opera、Chrome、Safari……
    自动搜索 下拉单
    有符号数和无符号数间的比较.
    结构体指针在函数调用中的实例
    如何计算时间复杂度
    指针和引用的比较
    指针参数是如何传递内存的
    fread函数和fwrite函数,read,write
  • 原文地址:https://www.cnblogs.com/songer/p/4941864.html
Copyright © 2011-2022 走看看