收藏 分享(赏)

数论中的程序设计-new.ppt

上传人:无敌 文档编号:1359410 上传时间:2018-07-03 格式:PPT 页数:94 大小:878KB
下载 相关 举报
数论中的程序设计-new.ppt_第1页
第1页 / 共94页
数论中的程序设计-new.ppt_第2页
第2页 / 共94页
数论中的程序设计-new.ppt_第3页
第3页 / 共94页
数论中的程序设计-new.ppt_第4页
第4页 / 共94页
数论中的程序设计-new.ppt_第5页
第5页 / 共94页
点击查看更多>>
资源描述

1、第3次课 数论中的程序设计,沈云付,上海大学计算机工程与科学学院,本章主要内容,1、最大公因数与最小公倍数2、求整系数一次不定方程ax+by=c的解3、求解模线性方程4、求模m的逆元素算法5、模线性方程组与中国剩余定理6、模取幂运算与素数测试7、实例研究,1,2,3,4,5,6,7,8,9,1、最大公因数与最小公倍数,公约数和最大公约数的概念最大公约数的一种求法分解因子最大公约数性质与欧几里德转辗相除法欧几里德转辗相除法欧几里德算法实现,实例 求最大公因数,问题描述: 从输入文件中读取一组数据,求最大公因数。输入: 输入有若干行。每一行上有两个整数x,y,是一组测试数据,他们之间用一个空格隔开

2、。输出: 对每一组测试数据,每行输出这两个整数的最大公因数。如无最大公因数,则标明“no GCD”。,输出样例:(6,11)=1(0,0) no GCD(5,0)=5,输入样例: 6 110 05 0,1)公因数和最大公因数的概念,公因数:如果d是a的因数并且也是b的因数,则d是a与b的公因数例:30的正因数: 1,2,3,5,6,10,15、30; 24的正因数:1,2,3,4,6,12,24; 24与30的正公因数有:1、2、3、6。 1是任意两个整数的公因数;最大公因数:两个不同时为0的整数a与b的最大公因数是其值为最大的公因数,记作gcd(a, b)。 gcd(24, 30)6。,最大

3、公约数的一种求法分解因子,因为gcd(a,b)gcd(|a|,|b|),所以可考虑非负整数的情况。 通过求因数,可求a和b的素数因子分解: a= ,b= 于是整数a和b的最大公因数为: gcd(a,b),注意:求一个数的素因子分解问题是NP问题。目前用穷举方法可求不太大的整数的整数分解,这种方法不是有效的。只能用优化方法改善计算效率。,最大公因数性质,性质:(1)gcd(a,b)gcd( a, b)(2)gcd(a,b)gcd(a + kb, b),k为任何整数(3)gcd(a,b)gcd(b,a mod b)(4)如a是非零整数,那么gcd(a,0)|a|,欧几里德转辗相除法的依据: gcd

4、(a,b)gcd(b,a mod b) 可求整数a和b的最大公因数,2)最小公倍数,公倍数:如果m是a的倍数并且也是b的倍数,那么称m是a与b的公倍数。最小公倍数:两个非零整数a与b的最小公倍数是a与b的公倍数中数值最小正的数。记作lcm(a,b)(或简写为a,b)。lcm(a,b)lcm(|a|,|b|) 通过a和b的标准分解,可以求出整数a和b的最小公倍数: lcm(a,b)=,最小公倍数与最大公因数关系,3)欧儿里德算法,给定任意两个正整数a和b,gcd(a,b)=,结论:,求最大公因数的递归程序,用欧几里德转辗相除法构造一个求最大公因数的递归程序。输入:非负整数a、b返回:a和b的最大

5、公因数long gcd(long a, long b) long m; if (b=0),求最大公因数的无递归程序,int gcd(int a,int b) int c;if(a =0) return b; while(b!=0) c=b,b=a%b,a=c; return a;,2、利用欧几里德算法求整系数一次不定方程ax+by=c的解,算法思想:利用求a,b的最大公因数的转辗相除过程,进行多次逆推,使最大公因数的表示式最终表示为a与b的线性组合ax+by (x与y可能为0或负数) 。此时,dgcd(a,b)做法:将欧几里德算法进行推广,使得该算法不仅能得出任意两个正整数a和b的最大公因数d

6、,而且还能计算出满足下式的整数x和y:d=ax+by,反向递推,辗转相除过程的逆推,记,类似地,记,一般地,,于是有整数x和y满足: dgcd(a,b)ax+by,扩展欧几里德算法-递归实现,输入整数a、b,返回gcd(a,b)和对应等式ax+by=d中的x,y。long extend_gcd(long a, long b, long ,扩展欧几里德算法-无递归实现,int extend_gcd(int a, int b, int *x, int *y)int x0,x1,x2, y0,y1,y2;int r0,r1,r2, q;if(a= 0),if(b = 0) ,扩展欧几里德算法-无递归

7、实现(续),while(r1%r2) != 0) r0=r1;r1=r2;q= r0/r1;x2=x0-x1*q; y2=y0-y1*q;x0=x1;x1=x2; y0=y1; y1=y2;r2=r0 % r1;*x = x2; *y = y2;return r2; ,mx+ny=c的整数解算法,设d=gcd(m, n),记m=ad,n=bd求特解:求整系数方程mx+ny=d的一个整数解x0,y0,求一般解:若 d不是c的因数,则整系数方程mx+ny=c无整数解; 若 d是c的因数,记c=gd,则整系数方程mx+ny=c一般解为: x=gx0+bt, y=gy0-at, t为任何整数,举例,求

8、下列整系数方程的整数解:,答案:略,3、求解模线性方程,1) 模和同余模和同余:设a、b和m均为整数,且m0。如果a和b被m除所得的余数相同,那么称a和b关于模m是同余的,记作,几个等价定义:,2)同余性质,4、设 , ,,那么,1、2、3、,(1)(2)(3),5、费马小定理:设a,p为正整数,且p为素数,(p, a)=1, 那么,剩余类与简化剩余系,剩余类:对于整数a及模m,则集合A= x | xa (mod m) 称为模m关于a的一个剩余类。完全剩余系:0,1,2,m-1是一个特殊的集合,元素个数m,其中任何两个数都不同余,称为完全剩余系。任何m个元素的集合X,如果其中任何两个数都不同余

9、,那么X也是一个完全剩余系。既约剩余系:设m为正整数,在与m既约的所有剩余类中,每一个类中取一个数,构成一个集合X,则X称为模m的一个简化剩余系。,举例,例1:若p是素数,则1,2,3,p-1是模p的一个既约剩余系。例2:1,5,7,11是模12的一个既约剩余系。,问题:与正整数m既约且小于等于m的自然数全体之积Y被m除后余数是几?,举例:m=7,Y=1*2*3*4*5*6 (mod 7) -1 (mod 7) ,正余数为6;m=13,Y=1*2*3*4*5*12(mod 13) (-1)(13-1)/2 (mod 13) ,正余数为1;m=21,Y=1*2*4*5*8*10*11*13*16

10、*17*19*20Y (mod 21) 1 (mod 21),2)模线性方程,相当于求,根据前面求 的步骤:,(1)求 ,使,否则, 有d个解,(4) 的所有解可写为:,(3)由 ,改写得:,于是 的一个解为:,方程与同余式求解举例,(2)求(3)求,例:(1)求,4、求mod m的逆元素算法,对整数a,满足ax 1(mod m)的解x称为a关于模m的逆元素。是前面模线性方程的特例。结论:对整数a,m(m0), ax1(mod m)有解,当且仅当,gcd(a,m)=1也可用直接用扩展欧几里得算法进行求解。,求 的算法,举例,求解:(1)(2)(3)(4),求mod m的逆元素的无递归程序:,l

11、ong mod_reverse(long a, long m)long y=0,x=1,r=a%m, q, t, mm=m;/初始化if(r0)r=r+m;while(m%r) != 0) a=m; m=r;q= a/m; r=a % m;t=x; x=y-x*q; y=t;if(r!=1) return 0;if(x0) x=x+mm;return x;,5、模线性方程组与中国剩余定理,“韩信点兵”问题 : 有兵一列,三三数之余二,五五数之余三,七七数之余二,问兵几何?,可写成数学表示形式,求x,求解模线性方程组,中国剩余定理,求解步骤,例:解同余方程组,中国剩余定理程序实现,long Ch

12、inaRemainder(int m0, int b)long d,x,y,n,m=1,a=0; int i;for (i=1; i= n ; i+) m=m*m0i;for (i=1; i= n ; i+) MM=m / m0i;extend_gcd(MM, m0i, ,6、模幂运算与素数测试,模幂运算就是在一个模下计算一个幂的值,即计算 (a,r和m是正整数),素数测试就是指,在尽可能短的时间内,尽可能精确地判断一个整数是否是素数。通过费马小定理来判定一个整数的素性,因此求模幂是重要任务。,1)模幂运算,(1)模幂运算1累次计算法:d ar mod m (a mod m)*a) mod m

13、)*a)mod m*a)mod m 算法,long modular_power1(long a, long r, long m) long d=1, k; a=a % m; for(k=0;k0) if (r%2)=1) d=(d*t) % m; r=r/2; t=t*t % m; return d;,练习,计算,2)素数测试,费马小定理:设a,p为正整数,且p为素数,(p, a)=1, 那么,有例外,如2340 1(mod 341),但341是合数。,素数测试:设a、n为正整数 (1)若 ,则n一定为合数 (2)若 ,则几乎可以肯定地确认n为素数,因出错概率很小,Miller-Rabin素数

14、测试算法框架,输入:n与a(a在2,n-1这些数中随机取值)输出:true或false S1. 设(bk,bk-1,b1,b0)为n-1的二进制表示S2. d =1S3. For i=k downto 0 do x=d d= (d*d) mod n if (d=1) and (x1) and (xn-1) then return true if (bi=1) then d= (d*a)(mod n) End ForS4. if (d 1) then return true S5. return false,3)欧拉定理,设a和m 是整数,(m0)。记(m)是1到m的整数中与m互素的整数的个数,

15、则a(m) 1 (mod m)。费马小定理是欧拉定理的特例,4)公钥密码与RSA,公开密钥算法是在1976年由美国斯坦福大学的迪菲(Diffie)和赫尔曼(Hellman)提出目前最流行的RSA是1977年由MIT教授Rivest, Shamir和Adleman三人共同开发。,密钥的产生,选择两个大素数,p 和q ,计算出n=qp,n称为RSA算法的模数。 n公开,p、q 必须保密。n的长度大于1024位计算n的欧拉数 (n)=(p-1)(q-1) 。随机选择加密密钥e,从0, (n)-1中选择一个与(n)互质的数e,e公开计算解密密钥d, 满足de1(mod (n)。其中n和d也要互质。数e

16、和n做公钥,d做私钥。两个素数p和q不再需要,应该丢弃,不让任何人知道。,加密与解密,加密信息 m(二进制表示):首先把m分成等长数据块 m1,m2,.,mi,块长s,其中 2s n;do n/=5;count+=n;while(n);coutcount1,那么不能表示成Ax+By 形式的邮资的个数有无穷多,如以下数都不是Ax+By 形式:1、1+AB、1+2AB、1+nAB、 如d=gcd(A,B)=1,结果如何?,在0到AB-1内有 个整数m可以写成 m=As+Bt 的形式,s,t是非负整数。,分析,以下设d=gcd(A,B)=1。结论:值至少为AB的邮资都是可以用这两种邮票支付的。不能支

17、付的不超过AB-1个,而且可以用一个公式表示。需证明以下几点:不妨设AB。对整数n,0nB,有整数x、y,使n=Ax+By,且满足0=AB时,任何m均可表示成Ax+By的形式,x=0,y=0。不能表示成Ax+By形式的数的个数为,参考程序:易,略,4 Josephus问题,问题描述: Josephus问题:一群小孩围成一圈,任意给定一个数m,从第一个小孩开始,顺时针方向数,每数到第m个小孩时,该小孩便离开。小孩不断离开,圈子不断缩小。最后剩下的一个小孩是胜利者。究竟胜利者是第几个小孩呢?输入: 有若干组测试数据。每一行有一个整数num,m,分别代表小孩个数和每隔多少小孩数数。num,m1000

18、0。输出: 对每一组测试数据,单行输出获胜的小孩的编号。,输入与输出样例,输入样例:10 810 2输出样例:15,分析,方法一:模拟法实际模拟数小孩出列的过程。用一个数组表示小孩围成圈。对每个小孩赋以一个序号值作为小孩的标志。采用 “加1求模”,当数到数组尾的时候,下一个数组下标值可以算得为0,从而回到数组首以继续整个过程。设:Max=10000;小孩最大个数 num为小孩个数,aMax; 小孩数组 每次数m个小孩,便让该小孩离开;下标加1求模,使下标到达尾部后能返回到数组头。,参考代码一:见下页,#includeusing namespace std;int main()const int

19、 Max=10000; int num,m, aMax; while(cinnumm) for(int i=0;inum;i+) ai=i+1; /小孩编号 int k=1; /标识处理第k个小孩的离开 int i=-1; /初值 while(1)/圈中数m个小孩 for(int j=0;jm;) i=(i+1)%num;if(ai!=0) j+; ,if(k=num) break; /该小孩是最后一个吗? /是,则为胜利者 ai=0;/标识该小孩离开 k+;/准备处理圈中的 /下一个小孩 coutendl; cout ainumm) r=0;for(int k=1;k=num;+k) r=(

20、r+m)%k;coutr+1endl;return 0;,5 负数进制转换,问题描述(大意): 设计一个程序,读入一个十进制数和一个负进制的基数,并将此十进制数转换成为此负进制下的数: -R-2,-3,-4,.-20 例如,十进制数-15,相当于-2进制数110001:因110001=1*(-2)5+1*(-2)4+0*(-2)3+0*(-2)2+0*(-2)1+1*(-2)0,输入 输入的每行有两个数据N、-R。 N是十进制数,(-32768N32767),-R是负进制数的基数。输出 相对于每组输入,应输出此负进制数及其基数,若此基数超过10,则参照十六进制的方式处理。,输入与输出样例,分析

21、,采用与正数进制的转换相类似的方法。对负数进制,每次取的余数保证在0R-1之间,就可以直接输出。例如-R=-16,则余数应该在015。所以用模“%”运算符的时候必须注意检查是不是在该范围(可能在-R+10),否则就调整。调整的方法是: if (余数mbase) k=m; memset(a,0,sizeof(a); i=0; while(true) r=m%base; m=m/base;,if(r=0;i-) coutai; cout (base base; cout )endl; return 0;,任意范围基数转换表,char map(int temp)if(temp=9)return 0+

22、temp;elsereturn A+(temp-10);,6 数塔问题,问题描述 对任意正整数n,求由n层n构成的数的个位数。输入 输入文件的第1行是整数T,(0T=50),接下来的T行每行有一个整数n,(0n=1010)。输出 对输入中的每个n,对应于输出中的一行,内容是由n层n构成的数的个位数。,输入与输出样例,分析,设n的个位数为a,即,或n=10q+a,再设 的个位数为A,指数为m,那么由 得 A= 。,分情况对a进行讨论:a=09如果a=0,1,5或6,那么A仍分别为0,1,5或6。 如果a=2,那么21 2,22 4,23 8,24 6,25 2 (mod 10)2的幂2t的个位数

23、循环出现,周期是4 。如设指数t=4k+r,r=1,2,3,4,那么2t的个位数仅与r有关。,分析,(a=2):只需计算m被4除得的余数。因n为偶数,所以m也为偶数。如果n本身是2,那么A=4;在其他情况下,m的指数是也是偶数2p,此时m能被4除尽,即r=4。此时A=6。根据2.类似的讨论,以下简单地讨论:如果a=3,n=10q+3。再设q=2p+s。周期是4。设m的指数t=4k+r,r=1,2,3,4。若s=0,则m被4除的余数是3,此时A=7。若s=1,则m被4除的余数仍是1,此时A=3。如果a=4,周期是2。m是一个偶数,此时A=6。,分析,如果a=7,n=10q+7,周期是4 。若q为

24、奇数,则n被4除的余数是1,A=7。若q为偶数,则n被4除的余数是3,A=3。如果a=8,n=10q+8,周期是4 。幂m的底是n,为偶数,其指数也是偶数。在这种情况下,A=6。如果a=9,周期是2。A=9,7 幸运数,问题描述 中国人认为8是一个幸运数字。鲍勃也认为是这样,而且他有他自己的幸运数 L。现在他要构造他的幸运数,该数是仅由数字8组成且是L的倍数中最小的那个正整数。输入 输入有多组测试数据,每一组仅由一行上的一个正整数L构成,(1= L3)因子。 Case 1:L有因子16,那么无法找到这个幸运数H Case 2:L有因子5,那么无法找到这个幸运数H Case 3:L有因子2t(t

25、4)。设L= 2tm,m为无有因子5的奇数。,Case 3进一步讨论,表明 是m的倍数 所以有 这里,(9m,10)=1。 由欧拉定理,可得 由 得 由于k是所求数的最小长度,因此必有,Case 3算法,计算9m,并求欧拉函数值(9m),记M= (9m) 。求M的素因子分解,在M的因子中从较小的因子开始作为k,尝试验证 。判断:如果成立,那么就找到最小的k,终止查找。,8 哥德巴赫猜想,问题描述 哥德巴赫是一位德国的业余数学家。1742年,他写信给当时的数学家欧拉,信中提出如下猜想: 每个大于4的偶数都可以写成两个奇素数之和。 例如:8 = 3 + 5,3 和5都是奇素数, 20 = 3 +

26、17 = 7 + 13 42 = 5 + 37 = 11 + 31 = 13 + 29 = 19 + 23. 直到现在,仍未证明该猜想是否是真的。不管怎样,你的任务是对于100万以内的偶数验证哥德巴赫猜想。,输入 有多组测试数据,每组测试数据由一个偶数n构成(6n 1000000)。 当输入是0时表示输入结束。 输出 对每种测试数据,输出形如n = a + b的表达式,其中a和b是奇素数,加号应该用空格隔开,如下面的输出样例。如果有多对奇素数满足,仅取差b a最大的一组。如果没有这样的素数对,那么输出“Goldbachs conjecture is wrong.”,输入与输出样例,输入样例 8

27、20420 输出样例 8 = 3 + 520 = 3 + 1742 = 5 + 37,分析,对于偶数n,可以取不大于n/2的奇数p,记q=n-p,即写n=p+q。本题测试数据较弱,可用常规的判定素数的埃拉托色尼筛法做,直接判定p和q是否为素数。为求满足差ba最大的一组,只要从3开始到不大于n/2的奇数依次作为p。当n1000000时,采用常规方法,有超时的可能。也可尝试用Miller-Rabin素数测试该算法并不能保证待测整数一定是素数,但对素数测试的正确性随着测试次数的增加而增加。以下程序中采用了二次测试。,练习:四个素数之和问题,欧拉证明素数有无穷多个。但每个整数能表示成四个素数之和吗?我

28、也不知道这一答案,希望你能帮助我。我希望你能高效率地解决这一问题。输入:每行输入一个整数N(N=10000000),它是你需要把它表示成四个素数之和的数。输入直到文件结束为止。输出:对于每个输入行都有一个输出行,每行包含符合要求的四个素数。如果该数不能表示为四个素数之和,那么输出一行“Impossible.”。也可能有多组解,任何合理的解都将被接受。,输入与输出举例,输入样例243646 输出样例3 11 2 73 7 13 1311 11 17 7,9 for循环语句执行次数,问题描述 有一个C语言型的for循环语句: for (j = 0; (j-b)% p!= 0; j += a) st

29、atement; 即该循环中循环变量j的初值为0,只要(j-b)% p不等于0就加a值后进行循环。我们要知道语句“statement”执行了多少次。 输入: 输入有多组测试数据。每组数据由一行上的三个整数a, b, p 构成,数据之间空一格。这里假定a, b 和p满足0 a, b p,1 p 109。,输出 对每组测试数据,输出一个结果。如果for循环无法终止,那么输出“Infinite”,否则输出for循环执行的次数x,即要求x是满足0 x p 的最小整数。输入样例13 2 2457 2 18113 2 743 334 216,输出样例195240Infinite,网上练习,青蛙的约会: poj1061 时钟: Pku1166 Latex中作有向线段问题:SHU318二次剩余: SHU 201,

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 经济财会 > 贸易

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报