收藏 分销(赏)

2021年程序设计竞赛基础实训.doc

上传人:二*** 文档编号:4776635 上传时间:2024-10-12 格式:DOC 页数:25 大小:98.04KB 下载积分:5 金币
下载 相关
2021年程序设计竞赛基础实训.doc_第1页
第1页 / 共25页
本文档共25页,全文阅读请下载到手机保存,查看更方便
资源描述
程序设计竞赛基本实训22 1 解不等式 其中m为从键盘输入正整数,式中符号为二个“+”号后一种“-”号,即分母能被3整除时为“-”。 输入正整数m,输出满足不等式n。 测试数据: (1) m=4 (2) m=7 设计要点1: 式中浮现减运算,导致不等式解也许分段。 设立条件循环,每三项(包括二正一负)一起求和,得一种区间解。 然后回过头来一项项求和,得个别离散解。 为论述以便,记 (1) 通过循环知s(d+1)>m,且n=d+1为“-”,可得n=d为一种解; 而n=d+2时1.0/(n+3)为“+”,可得s(d+2)>m;后来各项中,“-”项不大于其前面“+”项,可知对于n>d+2有s(n)>m成立。 因而有区间解:n≥d (2) 在n<d时与否有解,逐个求和检查拟定离散解。这一步不能省,否则浮现遗解。 程序设计1: // 解不等式:m<1+1/2-1/3+1/4+1/5-1/6+...+-1/n #include <stdio.h> void main() { long d,n,m,k;double s; printf("\n 请输入m:");scanf("%d",&m); n=-2;s=0; while(s<=m) { n=n+3;s=s+1.0/n+1.0/(n+1)-1.0/(n+2);} d=n+1;s=0; // 可拟定区间解n≥d(1) for(k=1;k<=n;k++) { if(k%3>0) s=s+1.0/k; else s=s-1.0/k; if(s>m) printf(" n=%ld,",k); // 逐个得离散解 } printf("n>=%ld \n",d); } 程序运营示例: 请输入m:4 n=10151,n=10153,n>=10154 请输入m:7 n=82273511,n=82273513,n>=82273514 注意:要特别注意,不要把离散解遗失。 思考:如果把后一种离散解写入区间解中? 设计要点2: 为论述以便,记 (1) 通过循环累加,当加到s=s+1.0/n+1.0/(n+1)-1.0/(n+2);得s(n+2)>m,令d=n+1,可知:n≥d为解; (2) 此时,s(n)有也许不不大于m,因而在原s基本上s-1.0/d+1.0/(d+1)得s(n): 若s(n)>m,合并得区间解:n≥d-1; 若s(n)<m,区间解为:n≥d;(因可必定s(n-1)<m) 但s(n-2)尚有也许不不大于m,因而在上s基本上s+1.0/(d-2)-1.0/(d-1),得s(n-2): 若s(n-2)>m,得一种离散解:n=d-3; 若s(n-2)<m,没有离散解。 程序设计2: // 解不等式:m<1+1/2-1/3+1/4+1/5-1/6+...+-1/n #include <stdio.h> void main() { long d,n,m;double s; printf("\n 请输入m:");scanf("%d",&m); n=-2;s=0; while(s<=m) { n=n+3;s=s+1.0/n+1.0/(n+1)-1.0/(n+2);} d=n+1; // 可拟定区间解n≥d(1) s=s-1.0/d+1.0/(d+1); // 得s(n) if(s>m) printf(" n>=%ld \n",d-1); // 输出区间解 else printf(" n>=%ld \n",d); s=s+1.0/(d-2)-1.0/(d-1); // 得s(n-2) if(s>m) printf(" n=%ld \n",d-3); // 输出一种离散解 } 数据测试: 请输入m:4 n>=10153 n=10151 请输入m:7 n>=82273513 n=82273511 程序设计3:请判断如下程序与否对的? // 解不等式:m<1+1/2-1/3+1/4+1/5-1/6+...+-1/n #include <stdio.h> void main() { double n,m,s; printf("\n 请输入m:");scanf("%lf",&m); n=0;s=3.0/2; while(s<=m) { n=n+3;s=s-1.0/n+1.0/(n+1)+1.0/(n+2);} d=n+2; printf(" n=%.0f,",d); // 得一种离散解(1) s=s-1.0/(n+3)+1.0/(n+4);d=n+4; if(s>m) printf(" n>=%.0f\n",d); // 可拟定区间解n≥d(2) else printf(" n>=%.0f\n",d+1); // ?? } (1) 一方面s(d)>m,n=d为一种解; 而s(d-3)<=m,n=d-2为“-”项,其绝对值不不大于n=d-1“+”项,可得s(d-1)<m;且知n<d时无解。 同步由,可得s(d+1)<m,即n=d为一种离散解。 (2) 当s(n+4)>m时,后来“-”项绝对值不大于其前面“+”项,故得区间解n≥d; 当s(n+4)<=m时,因可知s(n+5)>m;但不能拟定s(n+6)>0,因而不能拟定n≥d+1为区间解! 2 求最大值 设指定区间[a,b]内正整数x,y,z,w满足 其中a≤x<y<z<w≤b,试求s=x+y+z+w最大值。 输入正整数a,b(1≤a<b<10000),输出s最大值。 测试数据: (1) a=500,b=1000 (2) a=1000,b= 设计要点:对每一组满足条件解,通过比较求得最大值。 程序设计: // 求最大值 #include <stdio.h> #include <math.h> void main() {long a,b,d,s,x,y,z,w,max; printf(" 请输入区间[a,b]上下限a,b:"); scanf("%ld,%ld",&a,&b); max=0; for(x=a;x<=sqrt(b*b/3);x++) for(y=x+1;y<=sqrt((b*b-x*x)/2);y++) for(z=y+1;z<=sqrt(b*b-x*x-y*y);z++) { d=x*x+y*y+z*z; w=(int)sqrt(d); // w为x,y,z平方和开平方 if(w>b) break; if(w*w==d) // 满足条件时记录 { s=x+y+z+w; if(s>max) max=s; } } printf(" s最大值为:%ld \n",max); } 数据测试: 请输入区间[a,b]上下限a,b:500,1000 s最大值为:2728 请输入区间[a,b]上下限a,b:1000, s最大值为:5496 3 带中转站交通路线 在某城区完整方格交通网中,中转站(a,b)与终点(m,n)为交通网中任意两交叉点,这里a,b,m,n为非负整数。 试记录从始点(0,0)经中转点(a,b)到终点(m,n)不同最短路线(路线中各段只能接近目的点而不能远离目的点)条数。(注:若a>m且b>n时,从(0,0)点至(a,b)点这一段容许通过(m,n)点) 交通网格示意图 输入非负整数a,b,m,n,输出从始点(0,0)经(a,b)到终点(m,n)最短路线条数。 测试数据: (1) a=9,b=7,m=20,n=12 (2) a=20,b=12,m=9,n=7 设计要点: 如果路线中没有设指定必经点,从始点(0,0)到终点(m,n)每一条路线共m+n段,其中横向m段,纵向n段,每一条不同路线相应从m+n个元素中取m个元素(以放置横向段)组合数,不同路线条数为 今设立了路线中必经点(a,b),须分如下两步记录。设从始点(0,0)到交叉点(a,b)不同路线条数为y,从交叉点(a,b)到终点(m,n)不同路线条数为z。据乘法原理,从始点(0,0)经(a,b)到终点(m,n)最短路线条数为yz。 为了求y,分如下两种情形计算: 1) 若a=0或b=0,即必经点与起点在横向或纵向同线,y=1。 2) 若a>0且b>0,即a,b为正整数时,y=。 为了求z,分如下两种情形计算: 1) 若m=a或n=b,即必经点与终点在横向或纵向同线,z=1。 2) 若m≠a且n≠b,必经点与终点在横向相差,在纵向相差,z=。 程序设计: // 带中转站最短路线 #include <stdio.h> #include <math.h> void main() { double a,b,c,d,m,n,k,y,z; printf(" 请输入正整数a,b:");scanf("%lf,%lf",&a,&b); printf(" 请输入正整数m,n:");scanf("%lf,%lf",&m,&n); y=1; if(a*b>0) for(k=1;k<=a;k++) y=y*(b+k)/k; // 计算C(a+b,a) z=1; if((m-a)*(n-b)!=0) { c=fabs(m-a);d=fabs(n-b); for(k=1;k<=c;k++) z=z*(d+k)/k; // 计算C(|m-a|+|n-b|,|m-a|) } printf(" 不同最短路线条数为:%.0f \n",y*z); } 数据测试: 请输入正整数a,b:9,7 请输入正整数m,n:20,12 不同最短路线条数为:49969920 请输入正整数a,b:20,12 请输入正整数m,n:9,7 不同最短路线条数为: 附无障碍无中转站交通路线问题程序: // 无障碍完整交通路线问题 #include <stdio.h> void main() { int k,m,n,x,y,z,f[50][50]; printf(" 请输入正整数m,n:");scanf("%d,%d",&m,&n); for(x=1;x<=m;x++) f[x][0]=1; for(y=1;y<=n;y++) f[0][y]=1; // 拟定边界条件 for(x=1;x<=m;x++) for(y=1;y<=n;y++) // 实行递推得目的值f(m,n) f[x][y]=f[x-1][y]+f[x][y-1]; printf(" 不同最短路线条数为:%d \n",f[m][n]); z=1; for(k=1;k<=m;k++) z=z*(n+k)/k; printf(" 不同最短路线组合数为:%d \n",z); } 请输入正整数m,n:7,10 不同最短路线条数为:19448 4 双码二部数序列 试求双码二部数升序序列第m项。 测试数据:m=;m=4 设计1: 把双码二部数升序序列第m项换算为n位第m0项。 注意到2位双码二部数共9*9=81个;3位双码二部数共2*9*9=2*81个;…… // 求双码二部数升序序列第m项 #include <stdio.h> #include <math.h> void main() { int a,b,a0,b0,i,n,m,m0,la,lb,la0,lb0,s; printf(" 请依次输入整数m:"); scanf("%d",&m); s=0;n=0; while(s<m) {n++;s=s+n*81;} m0=m-(s-n*81);n++;s=0; // 换算为n位第m0项 for(a=1;a<=9;a++) // 高部数字a从小到大枚举 { for(la=1;la<=n-2;la++) // 高部位数la分3环节枚举 { lb=n-la; for(b=0;b<=a-1;b++) { s++; // 变量s记录个数 if(s==m0) // 记录第m个数信息 { a0=a;b0=b;la0=la;lb0=lb;} } } la=n-1;lb=1; for(b=0;b<=9;b++) if(a!=b) // 当a=b时跳过 { s++; if(s==m0){ a0=a;b0=b;la0=la;lb0=lb;} } for(la=n-2;la>=1;la--) { lb=n-la; for(b=a+1;b<=9;b++) { s++; if(s==m0){ a0=a;b0=b;la0=la;lb0=lb;} } } } printf(" 双码二部数升序序列第%d个数为:",m); for(i=1;i<=la0;i++) printf("%d",a0); for(i=1;i<=lb0;i++) printf("%d",b0); printf(" \n"); printf(" (式中%d个%d,%d个%d)\n",la0,a0,lb0,b0); } 设计2: 从n=2位开始记录 // 求双码二部数从小到大排列第m个数 #include<stdio.h> void main() { int a,b,a0,b0,i,m,n,p,la,la0,lb0; printf(" 请输入整数m:"); scanf("%d",&m); n=1;p=0; while(1) { n++;p++;a=1;b=0;la=1; // 默认n位第1个为1后n-1个0 if(p==m) {a0=a;b0=b;la0=la;lb0=n-la0;break;} while(la<n-1 || a<9 || b<8) { p++; if(b==9) // 此时b不能增1,有如下2种选取 if(la==1){a++;b=0;} // ① a增1后,b从0开始 else {la--;b=a+1;} // ② a段长增1后,b从a+1开始 else if(b!=a-1) b++; // a与la不变,b增1 else if(la!=n-1){la++;b=0;} // a段长增1后,b从0开始 else if(b<8) b+=2; // b增2跳过a=b情形 if(p==m) {a0=a;b0=b;la0=la;lb0=n-la0;break;} } if(p==m) break; } printf(" 第%d个双码二部数为:%d(%d)%d(%d)\n",m,a0,la0,b,lb0); printf(" 其中从小到大第%d个数为:",m); for(i=1;i<=la0;i++) printf("%d",a0); for(i=1;i<=lb0;i++) printf("%d",b0); printf(" \n"); } 数据测试: 请依次输入整数m: 双码二部数升序序列第个数为:55999999 (式中2个5,6个9) 请依次输入整数m:4 双码二部数升序序列第4个数为: (式中4个8,19个2) 5 求代数和 设n为正整数,求和 式中各项符号为二正一负,分母符号为一正一负。 正整数n从键盘输入,输出和s四舍五入精准到小数点后5位。 输入n=100 输出: 输入n= 输出: // 求代数和1 #include <stdio.h> #include<math.h> void main() { long j,n; double ts,s; printf(" 请输入n:");scanf("%d",&n); j=0;ts=0;s=0; while(j<n) { j=j+1; if(j%2==0) ts=ts-(double)1/j; // ts为各项分母 else ts=ts+(double)1/j; if(j%3==0) s=s-sqrt(j)/ts; // 求代数和s else s=s+sqrt(j)/ts; } printf(" s=%.5f \n",s); } // 求代数和2 #include <stdio.h> #include<math.h> void main() { double j,n,ts,s; printf(" 请输入n:"); scanf("%lfd",&n); j=0;ts=0;s=0; while(j<n) { j=j+1; if(fmod(j,2)==0) ts=ts-1/j; // ts为各项分母 else ts=ts+1/j; if(fmod(j,3)==0) s=s-sqrt(j)/ts; // 求代数和s else s=s+sqrt(j)/ts; } printf(" s=%.5f \n",s); } 请输入n:100 s=324.74013 请输入n: s=28924.48725 请输入n: s=28989.22300 变通:设2<n≤,当n为什么值时,和s最接近? 6 合数世纪探求 1. 问题提出 20世纪100个年号[1901—]中有13个素数,而21世纪100个年号[,2100]中有14个素数。 那么,与否存在一种世纪100个年号中一种素数都没有? 定义一种世纪100个年号中不存在一种素数,即100个年号全为合数世纪称为合数世纪。 设计程序摸索第m(商定m<100)个合数世纪。 测试数据: (1) m=1 (2) m=10 2. 设计要点 应用穷举搜索,设立a世纪50个奇数年号(偶数年号无疑均为合数)为b,用k试商鉴别b与否为素数,用变量s记录这50个奇数中合数个数。 对于a世纪,若s=50,即50个奇数都为合数,找到a世纪为合数世纪,用n记录合数世纪个数。当n=m时打印输出a 世纪。 当n=m时退出循环结束。 3. 合数世纪程序设计 // 探求第1个与第m个合数世纪 #include <stdio.h> #include <math.h> void main() {long a,b,k;int m,n,s,x; printf(" 请拟定m:");scanf("%d",&m); a=1;n=0; while (1) {a++;s=0; // 检查a世纪 for(b=a*100-99;b<=a*100-1;b+=2) // 穷举a世纪奇数年号b {x=0; for(k=3;k<=sqrt(b);k+=2) if(b%k==0) {x=1;break;} if(x==0)break; // 当前为非合数世纪时,跳出循环进行下一种世纪探求 s=s+x; // 年号b为合数时,x=1,s增1 } if(s==50) // s=50,即50个奇数均为合数 { n++; if(n==m) printf(" 第%d个合数世纪为:%ld 世纪。\n",n,a); } if(n==m) break; } } 4. 程序运营示例 请拟定m:10 第1个合数世纪为: 16719世纪。 第10个合数世纪为: 58453世纪。 16719 世纪尽管是最早合数世纪,它100个年号为[1671801,1671900]全为合数。这是一种非常漫长年代,可谓天长地久,地老天荒! 7 分解质因数 整数分解质因数是最基本分解。例如,90=2*3*3*5,1960=2^3*5*7^2,前者为质因数乘积形式,后者为质因数指数形式。 把指定区间上所有整数分解质因数,每一整数表达为质因数从小到大顺序乘积形式。如果被分解数自身是素数,则注明为素数。 例如,92=2*2*23,91(素数!)。 分解: 1671861= 5845271= (1) 设计要点 对每一种被分解整数i,赋值给b(以保持鉴别运算过程中i不变),用k(从2开始递增取值)试商: 若不能整除,阐明该数k不是b因数,k增1后继续试商。 若能整除,阐明该数k是b因数,打印输出"k*";b除以k商赋给b(b=b/k)后继续用k试商(注意,也许有各种k因数),直至不能整除,k增1后继续试商。 按上述从小至大试商拟定因数显然为质因数。 循环取值k终值如何拟定,一定限度上决定了程序效率。终值定为i-1或i/2,无效循环太多。循环终值定为i平方根sqrt(i)可大大精简试商次数,此时如果有不不大于sqrt(i)因数(至多一种!),在试商循环结束后要注意补上,不要遗失。 如果整个试商后b值没有任何缩减,仍为原待分解数i,阐明i是素数,作素数阐明标记。 (2) 质因数分解乘积形式程序设计 // 质因数分解乘积形式 #include"math.h" #include <stdio.h> void main() {long int b,i,k,m,n,w=0; printf("[m,n]中整数分解质因数(乘积形式).\n"); printf("请输入m,n:"); scanf("%ld,%ld",&m,&n); for(i=m;i<=n;i++) // i为待分解整数 { printf("%ld=",i); b=i;k=2; while(k<=sqrt(i)) // k为试商因数 {if(b%k==0) {b=b/k; if(b>1) {printf("%ld*",k); continue; // k为质因数,返回再试 } if(b==1) printf("%ld\n",k); } k++; } if(b>1 && b<i) printf("%ld\n",b); // 输出不不大于i平方根因数 if(b==i) {printf("(素数!)\n");w++;} // b=i,表达i无质因数 } printf("其中共%d个素数.\n",w); } 1671861=3*31*17977 5845276=2*2*223*6553 [m,n]中整数分解质因数(乘积形式) 请输入m,n:1671801,1671899 (验证第1个倒数世纪年号) 1671801=3*23*24229 1671802=2*11*75991 1671803=7*238829 1671804=2*2*3*3*46439 1671805=5*239*1399 1671806=2*769*1087 1671807=3*557269 1671808=2*2*2*2*2*2*2*37*353 1671809=599*2791 1671810=2*3*5*7*19*419 1671811=137*12203 1671812=2*2*417953 1671813=3*3*3*11*13*433 1671814=2*17*49171 1671815=5*334363 1671816=2*2*2*3*41*1699 1671817=7*241*991 1671818=2*835909 1671819=3*557273 1671820=2*2*5*83591 1671821=29*57649 1671822=2*3*3*131*709 1671823=191*8753 1671824=2*2*2*2*7*11*23*59 1671825=3*5*5*22291 1671826=2*13*64301 1671827=61*27407 1671828=2*2*3*127*1097 1671829=19*87991 1671830=2*5*31*5393 1671831=3*3*7*7*17*223 1671832=2*2*2*53*3943 1671833=1289*1297 1671834=2*3*278639 1671835=5*11*113*269 1671836=2*2*417959 1671837=3*47*71*167 1671838=2*7*119417 1671839=13*128603 1671840=2*2*2*2*2*3*3*3*3*3*5*43 1671841=1223*1367 1671842=2*109*7669 1671843=3*557281 1671844=2*2*417961 1671845=5*7*37*1291 1671846=2*3*11*73*347 1671847=23*72689 1671848=2*2*2*17*19*647 1671849=3*3*431*431 1671850=2*5*5*29*1153 1671851=67*24953 1671852=2*2*3*7*13*1531 1671853=101*16553 1671854=2*835927 1671855=3*5*227*491 1671856=2*2*2*2*104491 1671857=11*11*41*337 1671858=2*3*3*293*317 1671859=7*238837 1671860=2*2*5*179*467 1671861=3*31*17977 1671862=2*835931 1671863=359*4657 1671864=2*2*2*3*69661 1671865=5*13*17*17*89 1671866=2*7*119419 1671867=3*3*3*19*3259 1671868=2*2*11*37997 1671869=83*3 1671870=2*3*5*23*2423 1671871=487*3433 1671872=2*2*2*2*2*2*151*173 1671873=3*7*79613 1671874=2*835937 1671875=5*5*5*5*5*5*107 1671876=2*2*3*3*46441 1671877=79*21163 1671878=2*13*64303 1671879=3*11*29*1747 1671880=2*2*2*5*7*7*853 1671881=331*5051 1671882=2*3*17*37*443 1671883=43*59*659 1671884=2*2*47*8893 1671885=3*3*5*53*701 1671886=2*19*43997 1671887=7*238841 1671888=2*2*2*2*3*61*571 1671889=521*3209 1671890=2*5*11*15199 1671891=3*13*163*263 1671892=2*2*31*97*139 1671893=23*157*463 1671894=2*3*3*3*7*4423 1671895=5*334379 1671896=2*2*2*103*2029 1671897=3*181*3079 1671898=2*41*20389 1671899=17*98347 其中共0个素数. 8 记录 试记录具有数字7且不能被7整除m位整数个数s1,并指出这s1个数中不具有数字4整数个数s2。 输入m,输出s1,s2。 测试数据: m=5,输出: m=6,输出: 9 真分数最值 记录分母在指定区间[a,b]最简真分数(分子不大于分母,且分子分母无公因数)共有多少个,并求其中最接近指定分数x/y最简真分数。 输入a,b,输出[a,b]中最简真分数个数、指出最接近417/最简真分数。 测试数据: a=10,b=99,输出: a=100,b=999,输出: 10 特定数字构成平方数 用数字2,3,5,6,7,8,9可构成多少个没有重复数字7位平方数? 11 构建横竖折对称方阵 试观测图所示横竖折对称方阵构造特点,总结归纳其构造规律,设计并输出n(奇数)阶对称方阵。 图 7阶横竖对称方阵 输出15阶、19阶横竖折对称方阵。
展开阅读全文

开通  VIP会员、SVIP会员  优惠大
下载10份以上建议开通VIP会员
下载20份以上建议开通SVIP会员


开通VIP      成为共赢上传

当前位置:首页 > 包罗万象 > 大杂烩

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        抽奖活动

©2010-2026 宁波自信网络信息技术有限公司  版权所有

客服电话:0574-28810668  投诉电话:18658249818

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :微信公众号    抖音    微博    LOFTER 

客服