常用数论算法

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.
                             
时间: 2024-07-28 23:31:49

常用数论算法的相关文章

常用的算法思想总结

对于计算机科学而言,算法是一个非常重要的概念.它是程序设计的灵魂,是将实际问题同解决该问题的计算机程序建立起联系的桥梁.接下来,我们来看看一些常用的算法思想. (一)穷举法思想 穷举法,又称为强力法.它是一种最为直接,实现最为简单,同时又最为耗时的一种解决实际问题的算法思想. 基本思想:在可能的解空间中穷举出每一种可能的解,并对每一个可能解进行判断,从中得到问题的答案. 使用穷举法思想解决实际问题,最关键的步骤是划定问题的解空间,并在该解空间中一一枚举每一个可能的解.这里有两点需要注意,一是解空

DotNet常用排序算法总结

数据结构和算法对一个程序来说是至关重要的,现在介绍一下几种算法,在项目中较为常用的算法有:冒泡排序,简单选择排序,直接插入排序,希尔排序,堆排序,归并排序,快速排序等7中算法. 现在介绍选择排序算法,希尔排序算法,快速排序算法. (1).选择排序算法:通过n-i次关键字间的比较,从n-i+1个记录中选择出关键字最小的记录,并和第i(1大于等于i小于等于n)个记录交换. (2).希尔排序:先取一个小于n的整数d1作为第一个增量,把文件的全部记录分组.所有距离为d1的倍数的记录放在同一个组中.先在各

常用MD5算法代码

常用的MD5算法代码日期: 2014年8月4日作者: 铁锚 MD5,全称为 Message Digest Algorithm 5(消息摘要算法第五版).详情请参考 维基百科:MD5 MD5加密后是一个字节数组, 但我们一般是取其十六进制的字符串表示法,当然,十六进制数字符串是区分大小写,在 mysql数据库,Java,和JavaScript语言中,一般是使用小写的字符串来表示, 而在 Oracle数据库官方提供的包中,返回的是大写字符串,这算是一个坑,如果你想要执行多次 md5,可能需要转换为小

Java常用排序算法+程序员必须掌握的8大排序算法+二分法查找法

Java 常用排序算法/程序员必须掌握的 8大排序算法 本文由网络资料整理转载而来,如有问题,欢迎指正! 分类: 1)插入排序(直接插入排序.希尔排序) 2)交换排序(冒泡排序.快速排序) 3)选择排序(直接选择排序.堆排序) 4)归并排序 5)分配排序(基数排序) 所需辅助空间最多:归并排序 所需辅助空间最少:堆排序 平均速度最快:快速排序 不稳定:快速排序,希尔排序,堆排序. 先来看看 8种排序之间的关系: 1.直接插入排序 (1)基本思想:在要排序的一组数中,假设前面(n-1)[n>=2]

常用推荐系统算法总结

一,常用推荐系统算法总结 1.Itemcf (基于商品的协同过滤) 这个算法是cf中的一种,也是当今很多大型网站都在采用的核心算法之一.对于商城网站(以Amazon为代表,当然也包括京东那种具有搞笑特色的推荐系统在内),影视类推荐,图书类推荐,音乐类推荐系统来说,item的增长速度远不如user的增长速度,而且item之间的相似性远不如user之间的相似性那么敏感,所以可以在离线系统中将item的相似度矩阵计算好,以供线上可以近乎即时地进行推荐.因为这种方法靠的是item之间的相关性进行推荐,所

常用排序算法比较与分析

一.常用排序算法简述 下面主要从排序算法的基本概念.原理出发,分别从算法的时间复杂度.空间复杂度.算法的稳定性和速度等方面进行分析比较.依据待排序的问题大小(记录数量 n)的不同,排序过程中需要的存储器空间也不同,由此将排序算法分为两大类:[内排序].[外排序]. 内排序:指排序时数据元素全部存放在计算机的随机存储器RAM中. 外排序:待排序记录的数量很大,以致内存一次不能容纳全部记录,在排序过程中还需要对外存进行访问的排序过程. 先了解一下常见排序算法的分类关系(见图1-1) 图1-1 常见排

七种常用排序算法

七种常用排序算法 一.常见排序算法一览: 时间复杂度: 是一个函数,它定量描述了该算法的运行时间. 空间复杂度:一个算法在运行过程中临时占用存储空间大小的量度. 稳定性:保证排序前2个相等的数其在序列的前后位置顺序和排序后它们两个的前后位置顺序相同就稳定,反之不稳定. 视觉直观感受 7 种常用的排序算法 二.算法C#实现: 1. 直接插入排序: using System; using System.Collections.Generic; using System.Linq; using Sys

常用排序算法之——归并排序

归并排序的原理: 如果数组的元素个数大于1,则: 将数组平均分为两部分: 左边的数组归并排序:递归 右边的数组归并排序:递归 将两个各自有序的数组合并,需要一个额外的辅助数组,暂时保存合并结果:返回 否则,数组元素个数为1时,已经有序:直接返回. 稳定排序.时间复杂度在最坏.最好.平均情况下都为O(N lgN),空间复杂度为O(N). 代码: 1 #include <iostream> 2 using namespace std; 3 4 template<typename T>

常用排序算法之——快速排序

快速排序的原理: 首先找一个标兵值,等于某一个元素值:遍历数组,将数组分为小于标兵值和大于标兵值的两部分:然后分别对两个部分采用快速排序,递归. 分开数组时,维持一个指针,指向已找到小部分的最后一个元素:一个指针用于遍历. 不稳定排序算法.当数组已经有序时,时间复杂度最差,为O(N2),平均.最优情况下都为O(N lgN). 代码如下: 1 #include <iostream> 2 using namespace std; 3 4 template<typename T> 5 v