程序设计大赛题目解答.docx

上传人:b****4 文档编号:4409218 上传时间:2022-12-01 格式:DOCX 页数:38 大小:35.50KB
下载 相关 举报
程序设计大赛题目解答.docx_第1页
第1页 / 共38页
程序设计大赛题目解答.docx_第2页
第2页 / 共38页
程序设计大赛题目解答.docx_第3页
第3页 / 共38页
程序设计大赛题目解答.docx_第4页
第4页 / 共38页
程序设计大赛题目解答.docx_第5页
第5页 / 共38页
点击查看更多>>
下载资源
资源描述

程序设计大赛题目解答.docx

《程序设计大赛题目解答.docx》由会员分享,可在线阅读,更多相关《程序设计大赛题目解答.docx(38页珍藏版)》请在冰豆网上搜索。

程序设计大赛题目解答.docx

程序设计大赛题目解答

程序设计大赛题目解答

1.求代数和

设n为正整数,求和

式中各项符号为二正一负,分母符号为一正一负。

正整数n从键盘输入,输出和s四舍五入精确到小数点后5位。

输入n=100输出:

输入n=2011输出:

 

//求代数和

#include

#include

voidmain()

{longj,n;

doublets,s;

printf("请输入n:

");

scanf("%d",&n);

j=0;ts=0;s=0;

while(j

{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);

}

 

请输入n:

100s=324.74013

请输入n:

2011s=28924.48725

 

变通:

设2

#include

#include

voidmain()

{

intn,n1=1;

doublesum1=1,sum2=1,g;

printf("请输入n:

");

scanf("%d",&n);

while(n1

{

n1++;

if(n1%2==0)

sum2+=-(double)1/n1;

elsesum2+=(double)1/n1;

g=sqrt(n1);

if(n1%3==0)

sum1+=-g/sum2;

else

sum1+=g/sum2;

}

printf("%lf\n",sum1);

}

 

2.幂积序列

设x,y为非负整数,试计算集合

的元素不大于指定整数n的个数k,并求这些元素从小到大排序的第m项f。

输入n,m,输出k,f。

 

n=10000,m=50输出:

n=10000000,m=100输出:

 

 

幂积序列复杂在“积”字上,即幂积序列的项既可以是2的幂,3的幂,也可以是这双幂的乘积。

我们应用枚举求解。

(1)设计要点

集合元素由2的幂与3的幂及其乘积组成,设元素从小到大排序的第k项为f(k)。

显然,f

(1)=1,f

(2)=2。

设置a循环,a从3开始递增1至n,对每一个a(赋值给j),逐次试用2试商,然后逐次试用3试商。

试商后若j>1,说明原a有2,3以外的因数,不属于该序列。

若j=1,说明原a只有2,3的因数,属于该序列,把a赋值给序列第k项。

由于实施从小到大测试赋值,所得项无疑是从小到大的序列。

当a达到指定的n,退出循环,输出指定项f(m)。

(2)枚举程序设计

//幂序列2^x*3^y枚举求解

#include

voidmain()

{intk,m;

longa,j,n,f[1000];

printf("计算不大于n的项数,请指定n:

");

scanf("%ld",&n);

printf("输出序列的第m项,请指定m:

");

scanf("%d",&m);

f[1]=1;f[2]=2;k=2;

for(a=3;a<=n;a++)

{j=a;

while(j%2==0)j=j/2;//反复用2试商

while(j%3==0)j=j/3;//反复用3试商

if(j==1)

{k++;f[k]=a;}//用a给f[k]赋值

}

printf("幂序列中不大于%ld的项数为:

%d\n",n,k);

if(m<=k)

printf("从小到大排序的第%d项为:

%ld\n",m,f[m]);

else

printf("所输序号m大于序列的项数!

\n");

}

(3)程序运行示例

n=10000,m=50输出:

67,2304

n=10000000,m=100输出:

190,93312

 

变通:

计算集合在指定区间[n1,n2]中有多少个元素?

 

3.喝汽水

定价1瓶汽水4角8分钱,同时规定3个空瓶可换回1瓶汽水,或20个空瓶可换回7瓶汽水。

例如用5元买10瓶汽水,然后用9个空瓶子换3瓶汽水,喝掉3瓶满的,喝完以后4个空瓶子,用3个再换一瓶,喝掉这瓶满的,这时候剩2个空瓶子。

然后你让老板先借给你一瓶汽水,喝掉这瓶满的,喝完以后用3个空瓶子换一瓶满的还给老板。

这样,5元可喝到15瓶汽水。

今有n元钱买汽水,最多可喝m瓶汽水。

 

n=100,m=

n=2011,m=

 #include

voidmain()

{

intn1=2011,n,sum,i;

doublen2;

n2=n1/0.48;

n=n2;

sum=n;

while(n>20)

{

i=n/20;

sum+=i*7;

n=i*7+n%20;

}

while(n>=2)

{

i=n/3;

sum+=i;

n=i+n%3;

if(n==2)

{

sum++;break;

}

}

printf("%d\n",sum);

}

 

原题:

有这样一道智力题:

“某商店规定:

三个空汽水瓶可以换一瓶汽水。

小张手上有十个空汽水瓶,她最多可以换多少瓶汽水喝?

”答案是5瓶,方法如下:

先用9个空瓶子换3瓶汽水,喝掉3瓶满的,喝完以后4个空瓶子,用3个再换一瓶,喝掉这瓶满的,这时候剩2个空瓶子。

然后你让老板先借给你一瓶汽水,喝掉这瓶满的,喝完以后用3个空瓶子换一瓶满的还给老板。

如果小张手上有n个空汽水瓶,最多可以换多少瓶汽水喝?

 

//规定3个空瓶可换回1瓶汽水。

开始有n个空瓶,最多可喝多少瓶汽水?

#include

voidmain()

{longn,m,t,x;

printf("请输入开始拥有的空瓶数n:

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

t=n;m=0;//确定初始值

while(t>=3)

{x=t/3;m=m+x;//用3x个空瓶换回x瓶汽水

t=t-2*x;//空瓶数减少2x个

printf("用其中%ld个空瓶换回%ld瓶汽水。

",3*x,x);

printf("喝完后空瓶个数变为%ld.\n",t);

}

if(t==2)

{m=m+1;

printf("借1瓶汽水,再还3空瓶,两清.\n");

}

printf("答案:

开始有%ld个空瓶,可喝%ld瓶汽水。

\n",n,m);

}

 

请输入开始拥有的空瓶数n:

2012

用其中2010个空瓶换回670瓶汽水。

喝完后空瓶个数变为672.

用其中672个空瓶换回224瓶汽水。

喝完后空瓶个数变为224.

用其中222个空瓶换回74瓶汽水。

喝完后空瓶个数变为76.

用其中75个空瓶换回25瓶汽水。

喝完后空瓶个数变为26.

用其中24个空瓶换回8瓶汽水。

喝完后空瓶个数变为10.

用其中9个空瓶换回3瓶汽水。

喝完后空瓶个数变为4.

用其中3个空瓶换回1瓶汽水。

喝完后空瓶个数变为2.

借1瓶汽水,再还3空瓶,两清.

答案:

开始有2012个空瓶,可喝1006瓶汽水。

 

解:

因7/20>1/3,因此只要空瓶数大于等于20,尽可能用20个空瓶可换回7瓶汽水。

直到空瓶数不足20时,用3个空瓶可换回1瓶汽水。

由20空瓶=7汽水+7空瓶

得1空瓶=7/13汽水

由3空瓶=1汽水+1空瓶

得1空瓶=1/2汽水

设置变量k统计汽水瓶数,t统计空瓶数。

 

//规定1瓶汽水48分钱,今有n元钱;规定3个空瓶可换回1瓶汽水,

//或20个空瓶可换回7瓶汽水。

问最多可喝多少瓶汽水?

#include

voidmain()

{longk,n,t,x;

printf("请输入n:

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

k=n*100/48;t=k;//k为汽水瓶数,t为空瓶数

printf("有%ld元钱,可买回%ld瓶汽水。

",n,k);

if(n*100>k*48)printf("尚余%ld分钱。

",n*100-k*48);

printf("\n喝完%ld瓶汽水后,空瓶按以下方案换回汽水:

\n",k);

while(t>=20)

{x=t/20;k=k+7*x;//用20x个空瓶换回7x瓶汽水

t=t-13*x;//空瓶数减少13x个

printf("用其中%ld个空瓶换回%ld瓶汽水。

",20*x,7*x);

printf("喝完后空瓶个数变为%ld.\n",t);

}

if(t>=13)

{k=k+7;t=t-13;

printf("借7瓶汽水,再还20空瓶,空瓶个数变为%ld.\n",t);

}

while(t>=3)

{x=t/3;k=k+x;//用3x个空瓶换回x瓶汽水

t=t-2*x;//空瓶数减少2x个

printf("用其中%ld个空瓶换回%ld瓶汽水。

",3*x,x);

printf("喝完后空瓶个数变为%ld.\n",t);

}

if(t==2)

{k=k+1;

printf("借1瓶汽水,再还3空瓶.\n");

}

printf("答案:

有%ld元钱,最多可喝%ld瓶汽水。

\n",n,k);

}

请输入n:

100

有100元钱,可买回208瓶汽水。

尚余16分钱。

喝完208瓶汽水后,空瓶按以下方案换回汽水:

用其中200个空瓶换回70瓶汽水。

喝完后空瓶个数变为78.

用其中60个空瓶换回21瓶汽水。

喝完后空瓶个数变为39.

用其中20个空瓶换回7瓶汽水。

喝完后空瓶个数变为26.

用其中20个空瓶换回7瓶汽水。

喝完后空瓶个数变为13.

借7瓶汽水,再还20空瓶,空瓶个数变为0.

答案:

有100元钱,最多可喝320瓶汽水。

 

请输入n:

2011

有2011元钱,可买回4189瓶汽水。

尚余28分钱。

喝完4189瓶汽水后,空瓶按以下方案换回汽水:

用其中4180个空瓶换回1463瓶汽水。

喝完后空瓶个数变为147

用其中1460个空瓶换回511瓶汽水。

喝完后空瓶个数变为523.

用其中520个空瓶换回182瓶汽水。

喝完后空瓶个数变为185.

用其中180个空瓶换回63瓶汽水。

喝完后空瓶个数变为68.

用其中60个空瓶换回21瓶汽水。

喝完后空瓶个数变为29.

用其中20个空瓶换回7瓶汽水。

喝完后空瓶个数变为16.

借7瓶汽水,再还20空瓶,空瓶个数变为3.

用其中3个空瓶换回1瓶汽水。

喝完后空瓶个数变为1.

答案:

有2011元钱,最多可喝6444瓶汽水。

 

省去过程,简化设计:

//规定1瓶汽水48分钱,今有n元钱;规定3个空瓶可换回1瓶汽水,

//或20个空瓶可换回7瓶汽水。

问最多可喝多少瓶汽水?

#include

voidmain()

{longk,n,t,x;

printf("请输入n:

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

k=n*100/48;t=k;//k为汽水瓶数,t为空瓶数

x=t/13;k=k+7*x;//实现1空瓶=7/13瓶汽水

t=t-13*x;//空瓶数减少13x个

x=t/2;k=k+x;//实现1空瓶=1/2瓶汽水

printf("答案:

%ld元钱最多可喝%ld瓶汽水。

\n",n,k);

}

 

请输入n:

100

答案:

100元钱最多可喝320瓶汽水。

 

请输入n:

2011

答案:

2011元钱最多可喝6444瓶汽水。

 

 

4.解佩尔方程

1.案例背景

佩尔(Pell)方程是关于x,y的二次不定方程,表述为

(其中n为非平方正整数)

当x=1或x=-1,y=0时,显然满足方程。

常把x,y中有一个为零的解称为平凡解。

我们要求佩尔方程的非平凡解。

佩尔方程的非平凡解很多,这里只要求出它的最小解,即x,y为满足方程的最小正数的解,又称基本解。

对于有些n,尽管是求基本解,其数值也大得惊人。

这么大的数值,如何求得?

其基本解具体为多少?

可以说,这是自然界对人类计算能力的一个挑战。

十七世纪曾有一位印度数学家说过,要是有人能在一年的时间内求出x2-92y2=1的非平凡解,他就算得上一名真正的数学家。

由此可见,佩尔方程的求解是有趣的,其计算也是繁琐的。

输入n=92,方程的基本解:

输入n=73,方程的基本解:

 

 

2.枚举设计

应用枚举试值来探求佩尔方程的基本解。

设置y从1开始递增1取值,对于每一个y值,计算a=n*y*y后判别:

若a+1为某一整数x的平方,则(x,y)即为所求佩尔方程的基本解。

若a+1不是平方数,则y增1后再试,直到找到解为止。

应用以上枚举探求,如果解的位数不太大,总可以求出相应的基本解。

如果基本解太大,应用枚举无法找到基本解,可约定一个枚举上限,例如10000000。

可把y<=10000000作为循环条件,当y>10000000时结束循环,输出“未求出该方程的基本解!

”而结束。

3.程序设计

//解PELL方程:

x^2-ny^2=1

#include

#include

voidmain()

{doublea,m,n,x,y;

printf("解PELL方程:

x^2-ny^2=1.\n");

printf("请输入非平方整数n:

");

scanf("%lf",&n);

m=floor(sqrt(n+1));

if(m*m==n)

{printf("n为平方数,方程无正整数解!

\n");

return;

}

y=1;

while(y<=10000000)

{y++;//设置y从1开始递增1枚举

a=n*y*y;x=floor(sqrt(a+1));

if(x*x==a+1)//检测是否满足方程

{printf("方程x^2-%.0fy^2=1的基本解为:

\n",n);

printf("x=%.0f,y=%.0f\n",x,y);

break;

}

}

if(y>10000000)

printf("未求出该方程的基本解!

");

}

4.程序运行示例与说明

解PELL方程:

x^2-ny^2=1.

请输入非平方整数n:

73

方程x^2-73y^2=1的基本解为:

x=2281249,y=267000

为了提高求解方程的范围,数据结构设置为双精度(double)型。

如果设置为整形或长整形,方程的求解范围比设置为双精度型要小。

例如n=73时,设置整形或长整形就不可能求出相应方程的解。

可见,数据结构的设置对程序的应用范围有着直接的影响。

对某些n,相应佩尔方程解的位数太大。

例如当n=991时,相应佩尔方程的基本解达30位。

此时只有通过某些专业算法(例如连分数法)才能进行求解。

 

5.分解质因数

整数分解质因数是最基本的分解。

例如,90=2*3*3*5,1960=2^3*5*7^2,前者为质因数乘积形式,后者为质因数的指数形式。

把指定区间上的所有整数分解质因数,每一整数表示为质因数从小到大顺序的乘积形式。

如果被分解的数本身是素数,则注明为素数。

例如,92=2*2*23,91(素数!

)。

分解:

1671861=

5845271=

 

 

6.构建横竖折对称方阵

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

图7阶横竖对称方阵

 

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

10.统计

试统计含有数字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

 

变通:

求m(m>3)位整数中恰含有2个7且恰含有1个4的整数的个数.

 

11.构建斜折对称方阵

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

图7阶斜折对称方阵

 

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

 

 

 

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

斜折对称方阵的构造特点:

两对角线上均为“0”,依两对角线把方阵分为4个区域,每一区域表现为同数字依附两对角线折叠对称,至上下左右正中元素为n/2。

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

令m=(n+1)/2,按m把方阵分成的4个小矩形区如图所示。

图按m分成的4个小矩形

注意到方阵的主对角线(从左上至右下)上元素为:

i=j,则左上区与右下区依主对角线赋值:

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

注意到方阵的次对角线(从右上至左下)上元素为:

i+j=n+1,则右上区与左下区依次对角线赋值:

a[i][j]=abs(i+j-n-1);

(2)程序设计

//斜折对称方阵

#include

#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<=m&&j<=m||i>m&&j>m)

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

if(i<=m&&j>m||i>m&&j<=m)

a[i][j]=abs(i+j-n-1);//方阵右上部与左下部元素赋值

}

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

\n",n);

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

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

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

printf("\n");

}

}

 

运行以上两个程序,可以在欣赏各个具体的对称方阵中,感受从特例到一般的神奇。

 

12.台球碰撞

在平面直角坐标系下,台球桌是一个左下角在(0,0),右上角在(L,W)的矩形。

有一个球心在(x,y),半径为R的圆形母球放在台球桌上(整个球都在台球桌内)。

受撞击后,球沿极角为b的射线(即:

x正半轴逆时针旋转到此射线的角度为b)以初速度v飞出。

因球与桌面的磨擦,球作的加速度为a的匀减速率运动,每次碰到球桌边框时均发生完全弹性碰撞(反射角等于入射角)。

试求球停止时球心所在位置。

输入:

l=180,w=120,x=35,y=40,r=5,b=30,v=27,a=6

输出:

(87.61,70.37)

 

 

原题:

在平面直角坐标系下,台球桌是一个左下角在(0,0),右上角在(L,W)的矩形。

有一个球心在(x,y),半径为R的圆形母球放在台球桌上(整个球都在台球桌内)。

受撞击后,球沿极角为a的射线(即:

x正半轴逆时针旋转到此射线的角度为a)飞出,每次碰到球桌时均发生完全弹性碰撞(球的速率不变,反射角等于入射角)。

 

 

如果球的速率为v,s个时间单位之后球心在什么地方?

 

输入

输入文件最多包含25组测试数据,每个数据仅一行,包含8个正整数L,W,x,y,R,a,v,s(100<=L,W<=105,1<=R<=5,R<=x<=L-R,R<=y<=W-R,0<=a<360,1<=v,s<=105),含义见题目描述。

L=W=x=y=R=a=v=s=0表示输入结束,你的程序不应当处理这一行。

 

输出

对于每组数据,输出仅一行,包含两个实数x,y,表明球心坐标为(x,y)。

x和y应四舍五入保留两位小数。

 

样例输入

样例输出

1001008010590223

1101007010518019999

00000000

80.0056.00

71.0010.00

 

设计要点:

(1)

(1)确定球心区域

设球心座标为(x,y),则有球心矩形区域:

x1≤x≤x2,y1≤y≤y2

其中:

x1=r,x2=l-r;y1=r,y2=w-r

 

(2)没撞击时球位置

设开始时球心位于(x0,y0),球沿极角为a的射线射出,球的速率为v,s

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

当前位置:首页 > 解决方案 > 学习计划

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

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