程序设计竞赛基础实训.docx
《程序设计竞赛基础实训.docx》由会员分享,可在线阅读,更多相关《程序设计竞赛基础实训.docx(13页珍藏版)》请在冰豆网上搜索。
程序设计竞赛基础实训
2012程序设计竞赛基础实训82
39台球碰撞
在平面直角坐标系下,台球桌是一个左下角在(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
原题:
在平面直角坐标系下,台球桌是一个左下角在(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)确定球心区域
设球心座标为(x,y),则有球心矩形区域:
x1≤x≤x2,y1≤y≤y2
其中:
x1=r,x2=l-r。
y1=r,y2=w-r
(2)没撞击时球位置
设开始时球心位于(x0,y0),球沿极角为a的射线射出,球的速率为v,s个时间单位之后球心在(x,y):
x=x0+v*s*cos(a*3.14159/180)
y=y0+v*s*sin(a*3.14159/180)
(3)撞击轴对称
若球与右竖边(x2)撞击,撞击后横月座标为:
x=2*x2-x
若球与上横边(y2)撞击,撞击后纵月座标为:
y=2*y2-y
程序设计:
//台球碰撞
#include
#include
voidmain()
{
doublel,w,r,a,v,s,x,y,x1,x2,y1,y2。
printf("请确定球台边框(l,w):
")。
scanf("%lf,%lf",&l,&w)。
printf("请确定球心开始位置(x,y):
")。
scanf("%lf,%lf",&x,&y)。
printf("请确定球半径r:
")。
scanf("%lf",&r)。
printf("请确定射击角度a:
")。
scanf("%lf",&a)。
printf("请确定射击速度v:
")。
scanf("%lf",&v)。
printf("请确定时间s:
")。
scanf("%lf",&s)。
x1=r。
x2=l-r。
y1=r。
y2=w-r。
x=x+v*s*cos(a*3.1415926/180)。
y=y+v*s*sin(a*3.1415926/180)。
while(xx2||yy2)
{if(x>x2)x=2*x2-x。
if(xif(y>y2)y=2*y2-y。
if(y}
printf("所求位置为:
(%.2f,%.2f).\n",x,y)。
}
请确定球台边框(l,w):
130,110
请确定球心开始位置(x,y):
30,40
请确定球半径r:
5
请确定射击角度a:
30
请确定射击速度v:
20
请确定时间s:
20
所求位置为:
(113.59,40.00).
引申:
在平面直角坐标系下,台球桌是一个左下角在(0,0),右上角在(L,W)的矩形。
有一个球心在(x,y),半径为r的圆形母球放在台球桌上(整个球都在台球桌内)。
受撞击后,球沿极角为b的射线(即:
与正半轴逆时针旋转到此射线的角度为b)以初速度v飞出。
因球与桌面的磨擦,球作的加速度为a的匀减速率运动,每次碰到球桌边框时均发生完全弹性碰撞(反射角等于入射角)。
试求球停止时球心所在位置。
解:
球作的初速度为v0,加速度为a的匀减速率运动,设t时刻球的速度为vt,则
vt=v0-a*t
停止时vt=0,则运行时间为:
t=v0/a
球运行距离为s=v0*t-a*t*t/2=v0*v0/2/a
//台球碰撞
#include
#include
voidmain()
{
doublel,w,r,a,b,v,s,x,y,x1,x2,y1,y2。
printf("请确定球台边框(l,w):
")。
scanf("%lf,%lf",&l,&w)。
printf("请确定球心开始位置(x,y):
")。
scanf("%lf,%lf",&x,&y)。
printf("请确定球半径r:
")。
scanf("%lf",&r)。
printf("请确定射击角度b:
")。
scanf("%lf",&b)。
printf("请确定射击初速度v:
")。
scanf("%lf",&v)。
printf("请确定匀减速的加速度a:
")。
scanf("%lf",&a)。
x1=r。
x2=l-r。
y1=r。
y2=w-r。
s=v*v/2/a。
x=x+s*cos(b*3.1415926/180)。
y=y+s*sin(b*3.1415926/180)。
while(xx2||yy2)
{if(x>x2)x=2*x2-x。
if(xif(y>y2)y=2*y2-y。
if(y}
printf("球停止时球心所求位置为:
(%.2f,%.2f).\n",x,y)。
}
请确定球台边框(l,w):
180,120
请确定球心开始位置(x,y):
35,40
请确定球半径r:
5
请确定射击角度b:
30
请确定射击初速度v:
27
请确定匀减速的加速度a:
6
球停止时球心所求位置为:
(87.61,70.37).
40守形数
若正整数n是它平方数的尾部,则称n为守形数,又称同构数。
例如,6是其平方数36的尾部,76是其平方数5776的尾部,6与76都是守形数。
试求出指定区间[x,y]内所有守形数。
测试数据:
(1)x=10,y=10000,输出:
(2)x=10000,y=1000000,输出:
1.常规求解
(1)设计要点
对指定范围[x,y]内的每一个整数a(约定a>1),求出其平方数s;
计算a的位数w,同时计算b=10^w,a的平方s的尾部c=s%b;
比较a,c,若a=c则输出守形数。
(2)程序实现
//求[x,y]内的守形数
#include
voidmain()
{longinta,b,c,k,s,x,y。
printf("求区间[x,y]中的守形数.")。
printf("请输入整数x,y:
")。
scanf("%ld,%ld",&x,&y)。
for(a=x。
a<=y。
a++)
{s=a*a。
//计算a的平方数s
b=1。
k=a。
while(k>0)
{b=b*10。
k=k/10。
}
c=s%b。
//c为a的平方数s的尾部
if(a==c)
printf("%ld^2=%ld\n",a,s)。
}
}
(3)程序运行结果
求区间[x,y]中的守形数.请输入整数x,y:
10,10000
25^2=625
76^2=5776
376^2=141376
625^2=390625
9376^2=87909376
2.探索n位守形数
(1)求解要点
为了求更多位数的守形数,可应用守形数的性质:
一个m位守形数的尾部m-1位数也是一个守形数。
道理很简单,a是一个m位数,a的平方数尾部的m-1位仅由a的尾部m-1位决定而与a的其他位无关。
实施易知一位守形数有三个:
1,5,6。
则二位守形数的个位数字只可能是1,5,6这三个数字。
根据这一思路,我们可应用递推求出多位守形数。
(2)程序设计
//求n位守形数
#include
voidmain()
{intn,d,k,j,i,t,m,w,z,u,v,a[500],b[500],c[500]。
printf("n=")。
scanf("%d",&n)。
for(d=1。
d<=9。
d++)
{for(k=1。
k<=500。
k++)
{a[k]=0。
b[k]=0。
c[k]=0。
}
a[1]=d。
//给个位数赋值
for(k=2。
k<=n。
k++)
{for(j=0。
j<=9。
j++)
{a[k]=j。
v=0。
for(i=1。
i<=k。
i++)c[i]=0。
//探索a(k)
for(i=1。
i<=k。
i++)
{for(z=0,t=1。
t<=k。
t++)
{u=a[i]*a[t]+z。
z=u/10。
b[i+t-1]=u%10。
//计算平方
}
for(w=0,m=i。
m<=k。
m++)
{u=c[m]+b[m]+w。
w=u/10。
c[m]=u%10。
}
}
for(i=1。
i<=k。
i++)
if(a[i]!
=c[i])v=1。
if(v==0)break。
}
}
if(v==0&&a[n]!
=0)//输出n位守形数结果
{printf("%d结尾的%d守形数:
",a[1],n)。
for(k=n。
k>=1。
k--)
printf("%d",a[k])。
printf("\n")。
}
}
}
(3)程序运行示例
运行程序,输入n=30,得30位守形数
5结尾的30守形数:
1066199773922562599
6结尾的30守形数:
893380022607743740081787109376
41奇数序列运算式
在由指定相连奇数组成的序列的每相邻两项中插入运算符号:
若相邻两项都是合数,则两项中插入“-”号;
若相邻两项一项合数一项素数,则两项中插入“+”号;
若相邻两项都是素数,则两项中插入乘号“*”号;
输入奇数b,c(b例如b=31,c=45,完成运算式为:
31+33-35+37+39+41*43+45=1913
测试数据:
(1)b=3,c=51
(2)b=2011,c=2029
//奇数序列运算式
#defineN30000
#include
#include
voidmain()
{i