收藏 分销(赏)

2021年程序设计竞赛选拔赛实训.doc

上传人:二*** 文档编号:4745461 上传时间:2024-10-11 格式:DOC 页数:16 大小:56.54KB 下载积分:5 金币
下载 相关 举报
2021年程序设计竞赛选拔赛实训.doc_第1页
第1页 / 共16页
本文档共16页,全文阅读请下载到手机保存,查看更方便
资源描述
程序设计竞赛选拔赛(实训8) 1、排列数 由1个“1”,2个“2”,k个“3” (1≤k≤6)能构成多少个不同排列? 输入k,输出排列个数。 k=4, 输出: k=5, 输出: (1) 设计要点 注意到1个“1”,2个“2”,k个“3”构成k+3位数,一方面通过k+2个10相乘计算k+3位数起点b=10^(k+2),为枚举提供范畴t(b—4*b-1)。 为了检测k+3位数t具有多少个数字1、2、3,每个k+3位整数t赋给d(以保持t不变),然后通过k+3次求余先后分离出tk+3个数字c: if(c==1) f++,记录整数t中数字1个数f; if(c==2) g++,记录整数t中数字2个数g; if(c==3) h++,记录整数t中数字3个数h。 检测每一种k+3位整数:若f=1 and g=2 and h=k,则应用s进行记录。 最后输出所得排列个数s。 (2) 程序设计 // 排列数 #include <stdio.h> void main() { int c,f,g,h,i,j,k; long b,d,s,t; printf(" 请输入数字3个数k (1≤k≤6):");scanf("%d",&k); b=1;s=0; for(i=1;i<=k+2;i++) b=b*10; // 计算k+3位数起点 for(t=b;t<=4*b-1;t++) // 枚举首位为3k+3位数 { d=t;f=0;g=0;h=0; for(j=1;j<=k+3;j++) { c=d%10;d=d/10; if(c==1) f++; // 记录数字1个数 if(c==2) g++; // 记录数字2个数 if(c==3) h++; // 记录数字3个数 } if(f==1 && g==2 && h==k) s++; // 记录个数s } printf(" s=%ld \n",s); } (3) 程序运营示例 请输入数字3个数k (1≤k≤6):4 s=105 请输入数字3个数k (1≤k≤6):5 s=168 (4) 拓广 若需求k=100时排列数,如何求? 1) 注意到一排k个“3”空位共k+1个。 这k+1个选2个空位共C(k+1,2)种组合,每一空位放置1个“2”。 这k+1个选1个空位共C(k+1,1)种组合,空位中放置2个“2”。 2) 注意到一排k个“3”与2个“2”空位共k+3个。 这k+3个选1个空位共C(k+3,1)种组合,空位中放置1个“1”。 3) 因而得不同排列数为: (C(k+1,2)+C(k+1,1))*C(k+3,1)=(k+1)*(k+2)*(k+3)/2 // 排列数 #include <stdio.h> void main() { int k;long s; printf(" 请输入数字3个数k:");scanf("%d",&k); s=(k+1)*(k+2)*(k+3)/2; printf(" s=%ld \n",s); } 请输入数字3个数k:100 s=530553 (5) 实训1 计算由2个“1”、2个“2”、k个“3”排列数。 计算由3个“1”、2个“2”、k个“3”排列数。 测试数据:k=50 2、求最值 设n为正整数,,式中各项符号为二正一负。求当n为多大时,s(n)最接近指定正整数a? 输入a,输出s(n)最接近an,s(n)。 (1) 输入1000,输出: (2) 输入,输出: 解: 普通地求当n为多大时,s(n)最接近正整数a?其中a从键盘输入a。 // s(n)=1+1/(1+1/2)-1/(1+1/2+1/3)+...+1/(1+1/2+...+1/n) #include <stdio.h> #include<math.h> void main() { long a,n,n1; double m,ts,s,s1; printf(" 请输入a:"); scanf("%d",&a); n=0;ts=0;s=0;m=100000.0; while(s<a+10) { n=n+1; ts=ts+(double)1/n; // ts为各项分母 if(n%3==0) s=s-1/ts; // 求代数和s else s=s+1/ts; if(fabs(s-a)<m) // 比较,当n=n1时,和s1最接近a {m=fabs(s-a);n1=n;s1=s;} } printf(" n=%ld,s(%d)=%f \n",n1,n1,s1); } 请输入a:1000 n=29126,s(29126)=999.959989 请输入a: n=63376,s(63376)=.040087 实训2:设n为正整数,,式中各项符号为二正一负,分母符号一正一负。求当n为多大时,s(n)最接近指定正整数a? 输入a,输出s(n)最接近an,s(n)。 测试数据:a= 3、倒立勾股数 把求勾股数变通为求倒立勾股数。定义满足方程式 正整数x,y,z,称为一组倒立勾股数。 试求指定区间[a,b]内倒立勾股数组。 (1) 求指定区间[30,100]内倒立勾股数组. (2) 求指定区间[100,200]内倒立勾股数组. (1) 设计要点 显然,倒立勾股数组中x,y不也许相等,且x,y>z。为避免重复,不妨设x>y>z。 在指定区间[a,b]上依照x,y,z大小关系设立循环:z从a至b-2,y从z+1至b-1,x从y+1至b。 对每一组x,y,z,如果直接应用条件式 1/(x*x)+1/(y*y)=1/(z*z) 作鉴别,因分数计算不可避免误差,有也许把某些成立倒立勾股数组解遗失,即导致漏掉。 注意到上述分数条件式作通分整顿得到下面正整数条件式 z*z*(x*x+y*y)=x*x*y*y 程序中为防止发生解漏掉,应用上述整数条件作鉴别是适当。 (2) 求区间内倒立勾股数程序设计 // 求指定区间内倒立勾股数组 #include <stdio.h> #include <math.h> void main() {int a,b,n;long x,y,z; printf(" 求指定区间[a,b]内倒立勾股数组."); printf("\n 请输入区间[a,b]上下限a,b:"); scanf("%d,%d",&a,&b); printf("\n 区间[%d,%d]中倒立勾股数组有:\n",a,b); n=0; for(z=a;z<=b-2;z++) for(y=z+1;y<=b-1;y++) for(x=y+1;x<=b;x++) if(z*z*(x*x+y*y)==x*x*y*y) // 满足倒立勾股数条件时输出 {n++; printf(" 1/%ld^2+1/%ld^2=1/%ld^2 \n",x,y,z); } printf("共%d组勾股数.",n); } (3) 程序运营示例 区间[30,100]中倒立勾股数组有: 1/60^2+1/45^2=1/36^2 1/80^2+1/60^2=1/48^2 1/100^2+1/75^2=1/60^2 共3组勾股数. 区间[100,200]中倒立勾股数组有: 1/180^2+1/135^2=1/108^2 1/200^2+1/150^2=1/120^2 共2组勾股数. 4、双和数组 谋求6个互不相等正整数a,b,c,d,e,f并提成(a,b,c)与(d,e,f)两个组,若这两组数具备如下两个相等特性: 则把数组(a,b,c)与(d,e,f)称为双和数组(商定a<b<c,d<e<f,a<d)。 1) 设a+b+c=d+e+f=s,存在双和数组,s至少为多大? 2) 当s=98时有多少个不同双和数组? (1) 求解要点 从键盘输入整数s,因6个不同正整数之和至少为21,即输入整数s≥11。 设立a,b与d,e循环。注意到a+b+c=s,且a<b<c,因而a,b循环取值为: a:1——(s-3)/3。因b比a至少大1,c比a至少大2。 b:a+1——(s-a-1)/2。因c比b至少大1。 c=s-a=b。 设立d,e循环基本同上,只是d>a,因而d起点为a+1。 把比较倒数和相等1/a+1/b+1/c=1/d+1/e+1/f转化为比较整数相等 d*e*f*(b*c+c*a+a*b)=a*b*c*(e*f+f*d+d*e) (*) 若上式不成立,即倒数和不相等,则返回。 同步注意到两个3元组中若某些相似某些不同,不能有倒数和相等,因而可省略排除以上6个正整数中与否存在相等检测。 若式(*)成立,打印输出和为s双和数组,并用x记录解个数。 (2) C程序设计 // 双和数组摸索 #include<stdio.h> #include<math.h> void main() {int a,b,c,d,e,f,x,s; for(s=21;s<=100;s++) {printf(" s=%d:\n",s); x=0; for(a=1;a<=(s-3)/3;a++) for(b=a+1;b<=(s-a-1)/2;b++) for(d=a+1;d<=(s-3)/3;d++) for(e=d+1;e<=(s-d-1)/2;e++) {c=s-a-b;f=s-d-e; if(a*b*c*(e*f+f*d+d*e)!=d*e*f*(b*c+c*a+a*b)) continue; // 排除倒数和不相等 x++; printf("%3d:(%2d,%2d,%2d) ",x,a,b,c); printf("(%2d,%2d,%2d)\n",d,e,f); } if(x==0) printf(" 无解!\n"); } } (3) 程序运营成果与讨论 s=26: 1:( 4,10,12) ( 5,6,15) s=98: 1:( 2,36,60) ( 3,5,90) 2:( 7,28,63) ( 8,18,72) 3:( 7,35,56) ( 8,20,70) 4:(10,33,55) (12,20,66) (4) 实训3 谋求6个互不相等正整数a,b,c,d,e,f并提成(a,b,c)与(d,e,f)两个组,若这两组数具备如下两个相等特性: 则把数组(a,b,c)与(d,e,f)称为和积数组(商定a<b<c,d<e<f,a<d)。 1) 设a+b+c=d+e+f=s,存在和积数组,s至少为多大? 2) 当s=89时有多少个不同和积数组? 5、m位完美平方数 用0,1,2,...,9能构成多少个没有重复数字m(1<m≤10)位平方数? 输入m,输出没有重复数字m位平方数个数,并输出其中最大。 m=7,输出: m=10,输出: // 用0,1,2,...,9构成没有重复数字m位平方数 #include <math.h> #include <stdio.h> void main() {int k,m,n,t,f[10]; double a,b,c,d,w,x,a1,d1; printf(" 请拟定整数m:");scanf("%d",&m); x=1.0; for(k=2;k<=m;k++) x=x*10; // 拟定m位数起点x n=0; b=(int)pow(x,0.5);c=pow(10*x-1,0.5); for(a=b+1;a<=c;a++) {d=a*a;w=d; // 保证d为m位平方数 for(k=0;k<=9;k++) f[k]=0; while(w>0) { t=(int)fmod(w,10);f[t]=f[t]+1;w=floor(w/10);} for(t=0,k=0;k<=9;k++) if(f[k]>1) {t=1;break;} // 测试平方数与否有重复数字 if(t==0 ) // 测试平方数中没有重复数字 {n++;d1=d;a1=a;} } printf(" 共可构成%d个没有重复数字%d位平方数.",n,m); printf(" 其中最大为:%.0f=%.0f^2 \n",d1,a1); } 请拟定整数m:7 共可构成123个没有重复数字7位平方数. 其中最大为:9872164=3142^2 请拟定整数m:10 共可构成87个没有重复数字10位平方数. 其中最大为:=99066^2 实训4: 用0,1,2,...,9能构成没有重复数字m(1<m≤10)位平方数个数为s(m). 问: (1) 求s(10),即求出没有重复数字10位平方数个数。 (2)当m为多大时,没有重复数字m位平方数个数s(m)最大? 6、最小01串积 程序设计兴趣者A,B进行计算游戏: B任给一种正整数b,A谋求另一种整数a,使a 与b积最小且全为0与1构成数。 例如,B给出整数24,A谋求整数a:4625,使得a*b最小01串积为:111000 输入b,输出a与最小01串积。 b=24,输出: b=,输出: (1)对a枚举 考虑到a与积d也许不不大于10位,用双精度型。 对a递增枚举,检测积d=a*b与否为01串 // 01串积对a枚举 #include <math.h> #include <stdio.h> void main() { long c,t;double a,b,d,j; printf(" B给出整数b:");scanf("%lf",&b); a=1; while(1) {a++;d=a*b; j=d;t=0; while(j>0) // 分离积各个数字c { c=(int)fmod(j,10);j=floor(j/10); if(c>1) {t=1;break;} // 检测与否具有0,1以外数字 } if(t==0) { printf(" A谋求整数a:%.0f:\n",a); printf(" a*b最小01串积为:%.0f\n",d); break; } } } B给出整数b:73 A谋求整数a:137: a*b最小01串积为:10001 B给出整数b:54 A谋求整数a:: a*b最小01串积为: (2) 二进制枚举,应用余数鉴别。 1) 注意到01串积为十进制数,应用求余运算“%”可分别求得个位“1”,十位“1”,…,分别除以已给b余数,存储在c数组中:c(1)为1,c(2)为10除以b余数,c(3)为100除以b余数,…。 2) 要从小到大搜索01串,不重复也不漏掉,从中找出最小能被b整除01串积。为此,设立k从1开始递增,把k转化为二进制,就得到所需要这些串。但是,这时每个串不再看作二进制数,而要看作十进制数。 3) 在某一k转化为二进制数过程中,每转化一位a(i)(0或1),求出该位除以b余数a(i)*c(i),通过累加求和得k转化整个二进制数除以b余数s。 4) 鉴别余数s 与否被b整除:若s%b=0,即找到所求最小01串积。a 从高位开始除以b商存储在d数组,实行整数除法运算: x=e*10+a[j]; // e为上轮余数,x为被除数 d[j]=x/b; // d为a 从高位开始除以b商 e=x%b; // e为试商余数 去掉d数组高位“0”后,输出d即为所谋求数。 最后从高位开始打印a数组,即为01串积。 (3) 程序设计 // 01串积二进制枚举 #include<stdio.h> void main() { int b,e,i,j,t,x,a[],d[],c[]; long k,s; printf(" B给出整数b:");scanf("%d",&b); c[1]=1; for(i=2;i<200;i++) c[i]=10*c[i-1]%b; // c(i)为右边第i位1除以b余数 k=1; while(1) {k++;j=k;i=0;s=0; while(j>0) {i++;a[i]=j%2; s+=a[i]*c[i];j=j/2;s=s%b;// 除2取余法转化为二进制 } if(s%b==0) {for(e=0,j=i;j>=1;j--) {x=e*10+a[j]; d[j]=x/b;e=x%b; // a 从高位开始除以b商为d } j=i; while(d[j]==0) j--; // 去掉d数组高位"0" printf(" A谋求整数a:"); for(t=j;t>=1;t--) printf("%d",d[t]); printf("\n a*b最小01串积为:"); for(t=i;t>=1;t--) printf("%d",a[t]); printf("\n"); break; } } } (4) 程序运营示例 B给出整数b:54, A谋求整数a: a*b最小01串积为: B给出整数b:, A谋求整数a: a*b最小01串积为:11 (5) 实训5 1)任给一种正整数b,谋求另一种整数a,使a 与b积最小且全为0与5构成数。 2)任给一种正整数b,谋求另一种整数a,使a 与b积最小且全为2与5构成数。 3)任给一种正整数b,谋求另一种整数a,使a 与b积最小且全为0、1、2构成数。 测试数据:b=54; b=
展开阅读全文

开通  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 

客服