ImageVerifierCode 换一换
格式:DOCX , 页数:17 ,大小:23.69KB ,
资源ID:19473994      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/19473994.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(C语言程序设计漫谈之从最简真分数的个数谈起Word格式.docx)为本站会员(b****6)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

C语言程序设计漫谈之从最简真分数的个数谈起Word格式.docx

1、 能同时被2、3和5整除的数有 201035)=67 能同时被2、3和67整除的数有 201067)=5 能同时被2、5和67整除的数有 2010567)=3 能同时被3、5和67整除的数有 201067)=2 能同时被2、3、5和67整除的数有 201067)=1 这样,12010中能被2或3或5或67整除的数有 (1005+670+402+30)-(335+201+15+134+10+6)+(67+5+3+2)-1=2107-701+77-1=1482 因此,12010中既不能被2整除,也不能被3整除,也不能被5整除,也不能被67整除的数有 2010-1482=528 个。 即以2010为

2、分母的最简真分数有528个。 我们可以看出,上面的计算过程是比较繁琐的,需要认真仔细。 学习过程序设计后,可以编写了一个简单的循环程序解决这个问题。 用一个变量cnt来保存最简真分数的个数,初始值为0。 对12010中的每一个数num,进行判断,这是一个循环,写成for(num=1; num=2010;num+) 循环体中的判断方法为:如果num既不能被2整除,也不能被3整除,也不能被5整除,也不能被67整除,则计数。写成if(num%2!=0 & num%3! num%5! num %67!=0) cnt+; 最后,输出结果cnt。一个简单的程序,就得到问题的答案。编写的源程序如下:#inc

3、lude int main()int cnt,num;cnt=0;for (num=1; if (num%2!cnt+;printf(%dn,cnt);return 0; 需要说明的是,当时竞赛的真题是:所有以2010为分母的最简真分数的和为多少? 将上面的程序简单改写一下,可以很快得到答案的。int num;double sum;sum=0;if (num%2!sum+=1.0*num/2010;%lfn,sum); 程序运行后,输出 264.000000。即所有以2010为分母的最简真分数的和是264。 小朋友是没法像程序一样硬算的。1/2010+7/2010+11/2010+2099/2

4、010=264。 小朋友有小朋友的聪明,1/2010是最简真分数,那么2099/2010 也一定是最简真分数。 i/2010 是最简真分数,那么 (2010-i)/2010 也一定是最简真分数。 1/2010 + 2099/2010=1i/2010 +(2010-i)/2010=1。 小朋友知道了以2010为分母的最简真分数有528个,因此它们的和为 528/2 = 264。 因为2010分解质因数后,因数有2、3、5和67四个,用于考察集合的包含与容斥计算量略大但又可以完成,可以算是一道很好的竞赛试题。在这道试题的基础上,我们看这样一个问题。【例1】最简真分数。 任意输入一个正整数n,求以n

5、为分母的最简真分数有多少个?(1)编程思路1。 将输入的n作为分母,穷举分子i (1in-1)。因此,程序可先写成如下的循环:for (i=1; i=n-1; i+) 对每一分数i/n,进行是否存在公因数的检测。根据检测的结果决定是否计数; 在上面的循环体中需要对每一分数i/n,进行是否存在公因数的检测。如果分子i与分母n存在大于1的公因数k,说明i/n不是最简真分数,不予计数。怎样进行检测呢? 因为公因数k的取值范围为2,i,因而设置u循环在2,i中穷举k,若满足条件 i%k=0 & n%k=0 说明分子分母存在公因数k,标记t=1后退出。 在对因子k进行循环穷举前,可设置标志t=0。退出因

6、子穷举循环后,若t=1,说明分子和分母存在公因子;若保持原t=0,说明分子分母无公因数,统计个数。 (2)源程序1。 int n,i,k,t,cnt; while (scanf(%d,&n) & n!=0)ii+)/ 穷举分子 t=0; for (k=2;k=i;k+) / 穷举因数 if (i%k=0 & n%k=0) t=1;break; / 分子分母有公因数舍去if (t=0)/ 统计最简真分数个数 printf( return 0; 将上面的源程序提交给POJ 2407 “Relatives”,判定为Time Limit Exceeded。 POJ 2407的题意是:输入正整数N,求小

7、于或等于N (1,N),且与N互质的正整数(包括1)的个数。这与求最简真分数的意思完全一致。 上面源程序1的方法简单直接,但对于N值较大的话,会超时的。因此,我们应找到快速的求法。在数论中,欧拉函数就很好地解决了这样的问题。在数论,对于正整数n,欧拉函数是小于或等于n的正整数中与n互质的数的数目。此函数以其首名研究者欧拉命名,一般简记为函数。 例如,(8)=4,因为1,3,5,7均和8互质。 一般来说,设正整数N分解质因数后,N=P1q1*P2q2*.*Pnqn. 则(N)=N*(1-1/P1)*(1-1/P2)*.*(1-1/Pn)。 例如, 10= 2*5(10)=10(1-1/2)(1-

8、1/5)=4;这4个数是1, 3, 7, 9 。30=2*3*5(30)=30(1-1/3)(1-1/5)=8; 这8个数是1,7,11,13, 17, 19, 23, 29。按欧拉函数的求法,可以编写如下的源程序。 (3)源程序2。 int n,i,ans,t;, & ans = n; t=n; for (i=2;i*i=t;i+) if (t % i = 0)/ 找到一个质因数i ans -= ans/i; while (t % i = 0) / 将质因数i全去掉t /= i; if (t!=1) ans -= ans/t;,ans); 将源程序2提交给 POJ 2407, 可以Accep

9、ted。 将此源程序的printf(改写为,n-ans-1); 后,提交给HDU 1787 “GCD Again”,也可以Accepted。【例2】还是最简真分数。 输入一个正整数n,求分母在指定区间2,n的最简真分数共有多少个? 例如,输入5,输出应为 9。这9个最简真分数是 1/5, 1/4, 1/3, 2/5, 1/2, 3/5, 2/3, 3/4, 4/5 。 (1)编程思路。 例1的源程序2可以求欧拉函数(n)的值。用一个循环求出 (2)+(3)+(n)的累加和,即得本题的输出。 (2)源程序。 int n,i,k,ans,t,sum;for (k=2;=n;k+)ans = k;t

10、=k;for (i=2;if (t % i = 0) / 找到一个质因数i/ 将质因数i全去掉if (t!sum+=ans; 将此源程序提交给POJ 2478 “Farey Sequence”,被判定为Time Limit Exceeded。POJ 2478的题意是:求1n的欧拉函数的和。 因为,例1中是在O(sqrt(n) 的时间内求出一个数n的欧拉函数值。 如果要求100000以内所有正整数的欧拉函数值,上面程序采用的方法的复杂度将高达O(N*sqrt(N)。因此,容易超时。 下面我们寻求更快的求欧拉函数值的方法。 我们知道,欧拉函数值 (n)=n*(1-1/p1)*(1-1/p2).*(

11、1-1/pk),其中p1、p2pk为n的所有质因子。即欧拉函数的值与其质因子有关。用筛法可以方便地求出n以内的所有质数。 那么我们能不能在筛法求质数的同时求出所有数的欧拉函数呢?可以采用如下的方法:用筛法一边筛出N以内的所有质数,一边以类似于筛法的思想用质数筛出每个数的欧拉函数值。 这里,利用了欧拉函数的几个基本性质: 若N是质数p的k次幂,(N)=pk-p(k-1)=(p-1)p(k-1),因为除了p的倍数外,其他数都跟N互质。 当N是质数时,(N) = N-1。显然,因为N是质数,1N-1均与N互质。 欧拉函数是积性函数若m,n互质,(m*n)=(m)*(n) 。 假设质数p能整除n,那么

12、 如果p还能整除n / p , (n) = (n / p) * p; 如果p不能整除n / p,(n) = (n / p) * (p - 1)。 定义数组phiN,元素phii表示正整数i的欧拉函数值(i)。 定义数组visN,元素visi=True表示i在筛子中,visi=false表示i不在筛子中,已被筛掉。初始时,vis数组的元素全置为true,表示全部放在筛子中。定义数组primeN,元素primei的值为第i个质数。 下面以求20以内所有质数及所有数的值为例,来描述筛法的使用。 1) 从i=2开始循环, vis2=true,找到第一个质数2,prime0=2,质数个数PNum=1;同

13、时,phi2=2-1=1。 采用循环 for (j = 0; j pNum & primej*i #define MAXN 1000005int primeMAXN, pNum, phiMAXN;_int64 numMAXN=0;bool visMAXN; int n,i,j; memset(vis,true,sizeof(vis); / 下面程序段既求MAXN以内的素数又求欧拉数。 pNum=0; phi1 = 1; for (i = 2; i MAXN;if (visi)/ i是素数primepNum+ = i;phii = i-1;for (j = 0; j+ )visprimej*i

14、= false;if (i % primej = 0)phii*primej = phii * primej;elsephii*primej = phii *(primej - 1); numi=numi-1+phii;%I64dn,numn); 将用筛法思想改写的源程序提交给 POJ 2478, 可以Accepted。 将上面的程序略作改动,可以顺便通过HDU 2824 “The Euler function”。 (4)进一步讨论。上面采用筛法求欧拉函数的值时,用了3个数组,用于表示数是否在筛子中的标记数组vis,用于保存质数的数组prime,用于保存欧拉函数值的数组phi。虽然看起来直观,

15、好像体现了欧拉函数值与分解质因数相关的概念,但有点繁琐。能否只用一个数组phi,即保存欧拉函数的值,又表示筛子,当然在筛子中的最小数一定是质数,从而又表示了质数呢?定义数组phiN,初始值全为0,Phii=0表示i在筛子中,i是质数。 前面介绍过欧拉函数值得标准求法。 设正整数N分解质因数后,N=P1q1*P2q2*.*Pnqn.则显然,若p1是n的质因数,phin一定会作 n*(p1-1)/p1这样的运算。下面我以n=30为例介绍phi数组既保存欧拉函数值有当筛子用的方法。由于筛法从i=2开始进行,所有phii元素值初始全为0。 1)phi2=0,2在筛子中,2是质数,开始执行筛法过程,对指定范围内所有2的倍数进行处理。 phi2=0phi2=2(置初始值表示筛

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1