程序设计竞赛基础实训42.docx

上传人:b****6 文档编号:6327367 上传时间:2023-01-05 格式:DOCX 页数:22 大小:45.37KB
下载 相关 举报
程序设计竞赛基础实训42.docx_第1页
第1页 / 共22页
程序设计竞赛基础实训42.docx_第2页
第2页 / 共22页
程序设计竞赛基础实训42.docx_第3页
第3页 / 共22页
程序设计竞赛基础实训42.docx_第4页
第4页 / 共22页
程序设计竞赛基础实训42.docx_第5页
第5页 / 共22页
点击查看更多>>
下载资源
资源描述

程序设计竞赛基础实训42.docx

《程序设计竞赛基础实训42.docx》由会员分享,可在线阅读,更多相关《程序设计竞赛基础实训42.docx(22页珍藏版)》请在冰豆网上搜索。

程序设计竞赛基础实训42.docx

程序设计竞赛基础实训42

2012年程序设计竞赛基础实训42

1

8统计

试统计含有数字7且不能被7整除的m位整数的个数s1,并指出这s1个数中不含有数字4的整数的个数s2。

输入m,输出s1,s2。

m=5,输出:

m=6,输出:

(1)设计要点

首先通过乘m-1个10计算m位数的起点b=10^(m-1),为枚举提供范围t(b—10*b-1)。

为了检测m位数t含有多少个数字7,每个m位整数t赋给d(以保持t不变),然后通过m次求余先后分离出t的m个数字c,if(c==7)f++,统计整数t中数字7的个数f。

同时统计数字4的个数g。

如果f>0,说明整数t中含有数字7。

如果g=0,说明整数t中不含数字4。

对每一个m位整数,据f>0&&t%7>0,s1作相应统计。

据f>0&&t%7>0&&g==0,s2作相应统计。

(2)程序设计

//统计含数字7且不能被7整除的m位整数的个数s1,其中不含数字4的个数s2

#include

voidmain()

{intc,f,g,i,j,m;

longb,d,s1,s2,t;

printf("请输入位数m(2<=m<=9):

");scanf("%d",&m);

b=1;s1=0;s2=0;

for(i=2;i<=m;i++)b=b*10;//计算m位数的起点

for(t=b;t<=10*b-1;t++)//枚举每一个m位数

{d=t;

f=0;g=0;

for(j=1;j<=m;j++)

{c=d%10;d=d/10;

if(c==7)f++;//统计数字7的个数

if(c==4)g++;//统计数字4的个数

}

if(f>0&&t%7>0)s1++;//统计含数字7且不能被7整除数的个数

if(f>0&&t%7>0&&g==0)s2++;//统计其中不含数字4的个数

}

printf("s1=%ld,s2=%ld\n",s1,s2);

}

(3)程序运行示例

请输入位数m(2<=k<=9):

5

s1=32152,s2=20412

请输入位数m(2<=k<=9):

6

s1=366522,s2=208300

变通1:

试统计含有数字7且能被7整除的没有重复数字的m位整数的个数s1,并指出其中最大的一个数。

为了比较是否存在重复数字,设置f数组,f[3]=2为2个数字“3”。

#include

voidmain()

{intc,e,g,i,j,m,f[10];

longb,d,s1,t;

printf("请输入位数m(2<=m<=9):

");scanf("%d",&m);

b=1;s1=0;

for(i=2;i<=m;i++)b=b*10;//计算m位数的起点

for(t=b;t<=10*b-1;t++)//枚举每一个m位数

{d=t;

for(j=0;j<=9;j++)f[j]=0;//数组清零

for(j=1;j<=m;j++)

{c=d%10;d=d/10;

f[c]++;//统计数字c的个数

}

for(g=0,j=0;j<=9;j++)

if(f[j]>1)g=1;//存在重复数字标注g=1

if(f[7]>0&&t%7==0&&g==0)

{s1++;e=t;}//统计个数,并把满足条件的数赋值给e

}

printf("s1=%ld,e=%d\n",s1,e);

}

请输入位数m(2<=m<=9):

5

s1=1978,e=98763

请输入位数m(2<=m<=9):

6

s1=11704,e=987651

变通2:

试统计恰含一个数字7与2个数字4且能被7整除的m(m>3)位整数的个数s1,并指出其中从小到大排序的第n个数。

#include

voidmain()

{intc,e,i,j,m,n,f[10];

longb,d,s1,t;

printf("请输入m,n:

");scanf("%d,%d",&m,&n);

b=1;s1=0;

for(i=2;i<=m;i++)b=b*10;//计算m位数的起点

for(t=b;t<=10*b-1;t++)//枚举每一个m位数

{d=t;

for(j=0;j<=9;j++)f[j]=0;//数组清零

for(j=1;j<=m;j++)

{c=d%10;d=d/10;

f[c]++;//统计数字c的个数

}

if(f[7]==1&&f[4]==2&&t%7==0)

{s1++;

if(s1==n)e=t;//统计个数,并把第n个数赋值给e

}

}

printf("s1=%ld,e=%d\n",s1,e);

}

请输入m,n:

6,1000

s1=4096,e=417242

9真分数最值

统计分母在指定区间[a,b]的最简真分数(分子小于分母,且分子分母无公因数)共有多少个,并求其中最接近指定分数x/y的最简真分数。

输入a,b,输出[a,b]中最简真分数的个数、指出最接近417/2011的最简真分数。

测试数据:

a=10,b=99,输出:

a=100,b=999,输出:

(1)设计要点

设计求解一般情形:

统计分母在指定区间[a,b]的最简真分数的个数,并求这些最简真分数的和(正整数a,b从键盘输入)。

设分数分子为i,分母为j,最简真分数的个数为n,其和为s。

在指定范围[a,b]内枚举分数的分母j:

a——b;

同时对每一个分母j枚举分子i:

1——j-1。

对每一分数i/j,置标志t=0,然后进行是否存在公因数的检测。

如果分子i与分母j存在大于1的公因数u,说明i/j非最简真分数,应予舍略。

因为分子分母同时约去u后,分母可能不在[a,b],即使在[a,b]时前面已作了统计求和。

注意到公因数u的取值范围为[2,i],因而设置u循环在[2,i]中枚举,若满足条件

j%u==0&&i%u==0

说明分子分母存在公因数,标记t=1后退出,不予统计与求和。

否则保持原t=0,说明分子分母无公因数,用n实施迭代“n=n+1”统计个数。

为了求最接近s=x/y的最简真分数,设双精度型变量smin存储|i/j-x/y|的最小值,把分数i/j转变为double型减去s并求绝对值与smin比较,若fabs((double)i/j-s)

每得一个最简真分数i/j,就与smin比较一次。

枚举完成,则i1/j1即为所求最接近x/y的最简真分数。

(2)求最简真分数程序设计

//求分母在[a,b]的最简真分数的个数,及最接近x/y的分数

#include

#include

voidmain()

{inta,b,i,j,i1,j1,t,u,x,y;longn;

doubles,smin;

printf("最简真分数分母在[a,b]内,请确定a,b:

");

scanf("%d,%d",&a,&b);//输入区间的上下限

printf("指定分数为x/y,请确定x,y:

");

scanf("%d,%d",&x,&y);//输入指定分数

n=0;s=(double)x/y;smin=10;

for(j=a;j<=b;j++)//枚举最简真分数的分母

for(i=1;i<=j-1;i++)//枚举最简真分数的分子

{for(t=0,u=2;u<=i;u++)//枚举因数

if(j%u==0&&i%u==0)

{t=1;break;}//分子分母有公因数,则舍去

if(t==0)

{n++;//统计最简真分数个数

if(fabs((double)i/j-s)

{smin=fabs((double)i/j-s);i1=i;j1=j;}

//比较求最接近x/y的最简真分数

}

}

printf("最简真分数个数:

%ld\n",n);

printf("最接近%d/%d的最简真分数为:

%d/%d\n",x,y,i1,j1);

}

(3)程序运行示例

最简真分数分母在[a,b]内,请确定a,b:

10,99

指定分数为x/y,请确定x,y:

417,2011

最简真分数个数:

2976

最接近417/2011的最简真分数为:

17/82

最简真分数分母在[a,b]内,请确定a,b:

100,999

指定分数为x/y,请确定x,y:

417,2011

最简真分数个数:

300788

最接近417/2011的最简真分数为:

62/299

 

10特定数字组成的平方数

用数字2,3,5,6,7,8,9可组成多少个没有重复数字的7位平方数?

解:

求出最小7位数的平方根b,最大7位数的平方根c.

用a枚举[b,c]中的所有整数,计算d=a*a,这样确保所求平方数在d中。

设置f数组统计d中各个数字的个数。

如果f[3]=2,即平方数d中有2个“3”。

检测若f[k]>1(k=0——9),说明d中存在有重复数字,返回。

在不存在重复数字的情形下,检测若f[0]+f[1]+f[4]=0,说明7位平方数d中没有数字“0”,“1”,“4”,d满足题意要求,打印输出。

//组成没有重复数字的7位平方数

#include

#include

voidmain()

{intk,m,n,t,f[10];

longa,b,c,d,w;

n=0;

b=sqrt(2356789);c=sqrt(9876532);

for(a=b;a<=c;a++)

{d=a*a;w=d;//确保d为平方数

for(k=0;k<=9;k++)f[k]=0;

while(w>0)

{m=w%10;f[m]++;w=w/10;}

for(t=0,k=1;k<=9;k++)

if(f[k]>1)t=1;//测试平方数是否有重复数字

if(t==0&&f[0]+f[1]+f[4]==0)//测试平方数中没有数字0,1,4

{n++;

printf("%2d:

",n);

printf("%ld=%ld^2\n",d,a);

}

}

printf("共可组成%d个没有重复数字的7位平方数.\n",n);

}

1:

3297856=1816^2

2:

3857296=1964^2

3:

5827396=2414^2

4:

6385729=2527^2

5:

8567329=2927^2

6:

9572836=3094^2

共可组成6个没有重复数字的7位平方数.

变通1:

用1,2,…,9这9个数字可以组成多少个没有重复数字的9位平方数?

//组成没有重复数字的9位平方数

#include

#include

voidmain()

{intk,m,n,t,f[10];

longa,b,c,d,w;

n=0;

b=(int)sqrt(123456789);c=(int)sqrt(987654321);

for(a=b;a<=c;a++)

{d=a*a;w=d;//确保d为平方数

for(k=0;k<=9;k++)f[k]=0;

while(w>0)

{m=w%10;f[m]++;w=w/10;}

for(t=0,k=1;k<=9;k++)

if(f[k]>1)t=1;//测试平方数是否有重复数字

if(t==0&&f[0]==0)//测试平方数中没有重复数字,也没有数字0

{n++;

printf("%2d:

",n);

printf("%ld=%ld^2\n",d,a);

}

}

printf("共可组成%d个没有重复数字的9位平方数.\n",n);

}

1:

139854276=11826^2

2:

152843769=12363^2

3:

157326849=12543^2

4:

215384976=14676^2

5:

245893761=15681^2

6:

254817369=15963^2

7:

326597184=18072^2

8:

361874529=19023^2

9:

375468129=19377^2

10:

382945761=19569^2

11:

385297641=19629^2

12:

412739856=20316^2

13:

523814769=22887^2

14:

529874361=23019^2

15:

537219684=23178^2

16:

549386721=23439^2

17:

587432169=24237^2

18:

589324176=24276^2

19:

597362481=24441^2

20:

615387249=24807^2

21:

627953481=25059^2

22:

653927184=25572^2

23:

672935481=25941^2

24:

697435281=26409^2

25:

714653289=26733^2

26:

735982641=27129^2

27:

743816529=27273^2

28:

842973156=29034^2

29:

847159236=29106^2

30:

923187456=30384^2

共可组成30个没有重复数字的9位平方数.

11构建横竖折对称方阵

试观察图所示的横竖折对称方阵的构造特点,总结归纳其构造规律,设计并输出n(奇数)阶对称方阵。

图7阶横竖对称方阵

输出15阶、19阶横竖折对称方阵。

解:

这是一道培养与锻炼观察能力、归纳能力与设计能力的有趣案例。

设置2维数组a[n][n]存储n阶方阵的元素,数组a[n][n]就是数据结构。

本案例求解算法主要是给a数组赋值与输出。

一个一个元素赋值显然行不通,必须根据方阵的构造特点,归纳其构建规律,分区域给各元素赋值。

(1)构造规律与赋值要点

观察横竖折对称方阵的构造特点,方阵横向与纵向正中有一对称轴。

两对称轴所分4个小矩形区域表现为同数字横竖折递减,至4顶角元素为1。

设阶数n(奇数)从键盘输入,对称轴为m=(n+1)/2。

设置2维a数组存储方阵中元素,行号为i,列号为j,a[i][j]为第i行第j列元素。

可知主对角线(从左上至右下)有:

i=j;

次对角线(从右上至左下)有:

i+j=n+1。

按两条对角线把方阵分成上部、左部、右部与下部4个区,如图所示。

图对角线分成的4个区

对角线上元素可归纳到上、下部,即上、下部区域带等号即可。

上、下部按列号j的函数m-abs(m-j)赋值:

if(i+j<=n+1&&i<=j||i+j>=n+1&&i>=j)

a[i][j]=m-abs(m-j);

左、右部按行号i的函数m-abs(m-i)赋值:

if(i+jj||i+j>n+1&&i

a[i][j]=m-abs(m-i);

输出时,按m-a[i][j]打印。

(2)程序设计

//横竖折对称方阵

#include//调用2个头文件

#include

voidmain()

{inti,j,m,n,a[30][30];//定义数据结构

printf("请确定方阵阶数(奇数)n:

");scanf("%d",&n);

if(n%2==0){printf("请输入奇数!

");return;}

m=(n+1)/2;

for(i=1;i<=n;i++)

for(j=1;j<=n;j++)

{if(i+j<=n+1&&i<=j||i+j>=n+1&&i>=j)

a[i][j]=m-abs(m-j);//方阵上、下部元素赋值

if(i+jj||i+j>n+1&&i

a[i][j]=m-abs(m-i);//方阵左、右部元素赋值

}

printf("%d阶对称方阵为:

\n",n);

for(i=1;i<=n;i++)

{for(j=1;j<=n;j++)//输出对称方阵

printf("%3d",m-a[i][j]);

printf("\n");

}

}

12倒立的勾股数

把求勾股数变通为求倒立的勾股数。

定义满足方程式

的正整数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

#include

voidmain()

{inta,b,n;longx,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组勾股数.

13基于素数的代数和

定义s(n)=1*3-3*5-5*7+7*9+9*11±…-25*27±…±(2n-1)*(2n+1)

(一般项(2k-1)*(2k+1)的符号识别:

当(2k-1)与(2k+1)中有且只有一个素数,取“+”;其余取“-”。

1)求s(1000)。

2)设1<=n<=1000,当n为多大时,s(n)最大。

3)设1<=n<=1000,当n为多大时,s(n)最小。

(1)C程序设计

//基于素数的整数和

#include

#include

voidmain()

{intt,j,n,k,k1,k2,a[3000];longs,smax,smin;

printf("请输入整数n:

");

scanf("%d",&n);

for(k=1;k<=n+1;k++)a[k]=0;

for(k=2;k<=n+1;k++)

{for(t=0,j=3;j<=sqrt(2*k-1);j+=2)

if((2*k-1)%j==0)

{t=1;break;}

if(t==0)a[k]=1;//标记第k个奇数2k-1为素数

}

s=0;smax=0;smin=10000;

for(k=1;k<=n;k++)

{if(a[k]+a[k+1]==1)

s+=(2*k-1)*(2*k+1);//实施代数和

else

s-=(2*k-1)*(2*k+1);

if(s>smax){smax=s;k1=k;}//比较求最大值smax

if(s

}

printf("s(%d)=%ld\n",n,s);

printf("当k=%d时s有最大值:

%ld\n",k1,smax);

printf("当k=%d时s有最小值:

%ld\n",k2,smin);

}

(2)运行结果

请输入整数n:

300

s(300)=1142382

当k=255时s有最大值:

2986031

当k=174时s有最小值:

-174700

请输入整数n:

1000

s(1000)=-161348876

当k=387时s有最大值:

7076531

当k=985时s有最小值:

-181070411

14幂序列

1.问题提出

求解双幂集合

的元素由小到大排序的第n项与前n项之和。

输入正整数n,输出序列第n项与前n项之和。

测试数据:

(1)40

(2)46

2.幂序列求解要点

集合由2的幂与3的幂组成,实际上给出的是两个递推关系。

为了实现从小到大排列,设置a,b两个变量,a为2的幂,b为3的幂,显然a≠b。

设置k循环(k=1,2,…,n,其中n为键盘输入整数),在k循环外赋初值:

a=2,b=3,s=0。

在k循环中通过比较赋值:

当a

当a>b时,由赋值f(k)=b确定为序列的第k项;然后b=b*3,即b按递推规律乘3,为后一轮比较作准备。

每计算一项f(k),通过累加实现求和:

s=s+f(k)。

3.幂序列程序实现

//幂序列求解

#include

voidmain()

{intk,n,t,p2,p3;longa,b,s,f[100];

printf("求数列的第n项与前n项和,请输入n:

");

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

当前位置:首页 > 高等教育 > 历史学

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

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