《c++程序设计》课程设计报告
班级:数学四班 学号:2018212767__
报告人姓名:张子琪__________
实验地点:东校教学楼N409____________________
完成起止日期:2019.1.2-2019.1.5________
课设二
Problem Description E
把一个偶数拆成两个不同素数的和,有几种拆法呢?
Input
输入包含一些正的偶数,其值不会超过10000,个数不会超过500,若遇0,则结束。
Output
对应每个偶数,输出其拆成不同素数的个数,每个结果占一行。
解题思路:把一个偶数分别拆成两个数并判断两个数是否为素数。
源代码
#include
main()
{
int n,i,j,a,b,c,d;
while(scanf("%d",&n)!=EOF)
{
d=0;
if(n0)
return 0;
for(i=2;n/2>i;i++)
{
c=1;
for(j=2;i/2>=j;j++)
{
if(i%j0&&i!=j)
{
c=0;
break;
}
}
if(c1)
{
a=n-i;
b=1;
for(j=2;a/2>=j;j++)
{
if(a%j0&&a!=j)
{
b=0;
break;
}
}
if(b==1)
d+=1;
}
}
printf("%d\n",d);
}
}
Problem Description H
制作一个被掏空的字符三角形。
Input
每行包含一个字符和一个整数n(0
如果遇到@字符,结束这个程序。
Output
每个样板三角形之间应空上一行,三角形的中间为空。
行末没有多余的空格。
解题思路
由题意,输出的三角形所占据的空间为n行n-1列,前n-1行均需要先输出空格,且第一行空格个数为n-1,逐行递减,然后,从第二行开始,每行输出一个字符,设为m,再次输出空格,最后,在每一行行末输出一个m,紧接着输出换行,以上为一个大循环,可完成前n-1行的输出。对第n行,只需输出2n-1个字符m,即完成了空心三角形的输出。
细节处理
题目要求输入@时结束程序,则应添加:if(m==’@’) return 0;
关于最后的换行,多次提交错误后发现,题目要求
除最后一个三角形后有一个换行外,其余三角形后的换行均为两个。
所以将两个换行分开输出:
在程序最初定义一个i,并给这个i赋值为在程序中不可能出现的值,可设i=10000,并在输出三角形前加入:if(i!=10000) cout<<’\n’;
在之后的运行中,通过循环中的赋值使i不再等于10000,即从第二个三角形开始,每个三角形前后都有一个换行,而第一个三角形只有三角形后有换行。
源代码
#include
using namespace std;
int main()
{
int n,i=10000;
char m;
while(cin>>m)
{
if(m==’@’) return 0;
if(i!=10000)cout<<’\n’;
cin>>n;
for(i=1;i
for(int j=n-i;j>=1;j–)
cout<<" “;
if(i!=1) cout<
cout<<” “;
cout<
for(i=1;i<=2*n-1;i++)
cout<
}
return 0;
}
课设一
Problem Description B
春天是鲜花的季节,水仙花就是其中最迷人的代表,数学上有个水仙花数,他是这样定义的:
“水仙花数”是指一个三位数,它的各位数字的立方和等于其本身,比如:153=13+53+3^3。
现在要求输出所有在m和n范围内的水仙花数。
Input
输入数据有多组,每组占一行,包括两个整数m和n(100<=m<=n<=999)。
Output
对于每个测试实例,要求输出所有在给定范围内的水仙花数,就是说,输出的水仙花数必须大于等于m,并且小于等于n,如果有多个,则要求从小到大排列在一行内输出,之间用一个空格隔开;
如果给定的范围内不存在水仙花数,则输出no;
每个测试实例的输出占一行。
解题思路:①输入m,n表示范围 ②表示出符合水仙花数条件的数学表达式(个位十位百位) ③if语句判断是否为水仙花数。
解题细节:先输出第一个数,之后用循环语句输出空格和之后的符合条件的水仙花数。
源代码:
#include
using namespace std;
int main()
{
int m,n;
while(cin>>m>>n)
{
int j=0;
for(int i=m;i<=n;i++)
{
int a=i/100;
int b=(i-100a)/10;
int c=(i%100)%10;
if(i==aaa+bbb+cc*c)
{
j++;
if(j1) cout< else cout<<" "< }
}
if(j0) cout<<“no”;
cout<<"\n";
}
return 0;
}
Problem Description D
对于表达式n^2+n+41,当n在(x,y)范围内取整数值时(包括x,y)(-39<=x
输入数据有多组,每组占一行,由两个整数x,y组成,当x=0,y=0时,表示输入结束,该行不做处理。
Output
对于每个给定范围内的取值,如果表达式的值都为素数,则输出"OK",否则请输出“Sorry”,每组输出占一行。
解题思路:①在x和y的范围判断表达式nn+n+41的值是否都为素数
解题细节:注意for(int j=2;j
#include
using namespace std;
int main()
{
int x,y;
while(cin>>x>>y)
{
int a=1;
if(x0&&y0) return 0;
for(int i=x;i<=y;i++)
{
int m=i
for(int j=2;j
if(m%j0)
{
cout<<“sorry”<
}
if(a
}
if(a0) break;
}
if(a1) cout<<“OK”<
return 0;
}
Problem Description E
多项式的描述如下:
1 - 1/2 + 1/3 - 1/4 + 1/5 - 1/6 + …
现在请你求出该多项式的前n项的和。
Input
输入数据由2行组成,首先是一个正整数m(m<100),表示测试实例的个数,第二行包含m个正整数,对于每一个整数(不妨设为n,n<1000),求该多项式的前n项的和。
Output
对于每个测试实例n,要求输出多项式前n项的和。每个测试实例的输出占一行,结果保留2位小数。
解题思路:①在cmath中调用pow函数表示出多项式中的减号项 ②定义数组名避免与其它定义的字母重复
解题细节:①多组数据输入 ②用代码打出多项式求解
源代码:
#include
#include
#include
using namespace std;
int main()
{
int m,n[101];
while(cin>>m)
{
for(int i=1;i<=m;i++)
cin>>n[i];
for(int i=1;i<=m;i++)
{
double s=0,a;
int b;
for(double j=1;j<=n[i];j++)
{
a=1/j;
b=pow(-1,j+1);
s+=a*b;
}
printf("%.2f\n",s);
}
}
return 0;
}
Problem Description G
青年歌手大奖赛中,评委会给参赛选手打分。选手得分规则为去掉一个最高分和一个最低分,然后计算平均得分,请编程输出某选手的得分。
Input
输入数据有多组,每组占一行,每行的第一个数是n(2
对于每组输入数据,输出选手的得分,结果保留2位小数,每组输出占一行。
解题思路:关键在于去掉最大值与去掉最小值,之后求平均值
解题细节:①sort函数进行排序②区分循环语句1:for(int i=0;i
#include
#include
#include
using namespace std;
int main()
{
int n;
while(cin>>n)
{
double a[101];
double s=0,m;
for(int i=0;i
sort(a,a+n);
for(int i=1;i
m=(double)s/(n-2);
printf("%.2f",m);
cout<<"\n";
}
return 0;
}
Problem Description I
输入n(n<=100)个整数,按照绝对值从大到小排序后输出。题目保证对于每一个测试实例,所有的数的绝对值都不相等。
Input
输入数据有多组,每组占一行,每行的第一个数字为n,接着是n个整数,n=0表示输入数据的结束,不做处理。
Output
对于每个测试实例,输出排序后的结果,两个数之间用一个空格隔开。每个测试实例占一行。
错因:①n=0表示输入数据的结束,不作处理②空格的输出必须符合规范 结尾后面无空格。
解题思路:①取绝对值②swap函数排序③空格处理
解题细节:①循环②swap函数③讨论n=0需要结束程序这一情况
源代码:
#include
#include
#include
using namespace std;
int main()
{
int n;
while(cin>>n)
{
if(n==0) return 0;
int a[101],b[101];
for(int i=1;i<=n;i++)
cin>>a[i];
for(int i=1;i<=n;i++)
b[i]=abs(a[i]);
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
if(b[i] {
swap(b[i],b[j]);
swap(a[i],a[j]);
}
cout< for(int i=2;i<=n;i++)
cout<<" “< cout<<”\n";
}
return 0;
}
Problem Description J
有n(n<=100)个整数,已经按照从小到大顺序排列好,现在另外给一个整数x,请将该数插入到序列中,并使新的序列仍然有序。
Input
输入数据包含多个测试实例,每组数据由两行组成,第一行是n和m,第二行是已经有序的n个数的数列。n和m同时为0标示输入数据的结束,本行不做处理。
Output
对于每个测试实例,输出插入新的元素后的数列。
解题思路:①sort函数将整数排序②插入的数赋值给a[n] ③输出排序后的整数
解题细节:①输出a[0]时不用循环语句②sort排序要空出一位③输出a[0]后从a[1]开始运用循环语句输出.
源代码:
#include
using namespace std;
int main()
{
int n;
while(cin>>n)
{
if(n==0) return 0;
int a[101],b[101]={0};
for(int i=1;i<=n;i++)
cin>>a[i];
for(int i=1;i<=n;i++)
{
if(a[i]>=100)
{
b[i]=a[i]/100;
a[i]=a[i]%100;
}
if(a[i]>=50)
{
b[i]=b[i]+a[i]/50;
a[i]=a[i]%50;
}
if(a[i]>=10)
{
b[i]=b[i]+a[i]/10;
a[i]=a[i]%10;
}
if(a[i]>=5)
{
b[i]=b[i]+a[i]/5;
a[i]=a[i]%5;
}
if(a[i]>=2)
{
b[i]=b[i]+a[i]/2;
a[i]=a[i]%2;
}
if(a[i]>=1)
b[i]=b[i]+a[i];
}
int s=0;
for(int i=1;i<=n;i++)
s+=b[i];
cout<
}
Problem Description I
“回文串”是一个正读和反读都一样的字符串,比如“level”或者“noon”等等就是回文串。请写一个程序判断读入的字符串是否是“回文”。
Input
输入包含多个测试实例,输入数据的第一行是一个正整数n,表示测试实例的个数,后面紧跟着是n个字符串。
Output
如果一个字符串是回文串,则输出"yes",否则输出"no".
解题思路:①用循环语句表示出“自两边向中间字母比较是否相同”的代码 ②string.h函数表示字符的宽度(strlen)
解题细节:①若不符合左右字母相同,用break语句停止跳出 ②getchar()吸收空格
源代码:
#include
#include
int main()
{
int n,i,len,j;
char s[100];
scanf("%d",&n);
getchar();
while(n–)
{
gets(s);
len=strlen(s);
i=0;
j=len-1;
while(i
if(s[i]!=s[j])
break;
i++;
j–;
}
if(i>=j)
printf(“yes\n”);
else
printf(“no\n”);
}
return 0;
}
Problem Description
参加过上个月月赛的同学一定还记得其中的一个最简单的题目,就是{A}+{B},那个题目求的是两个集合的并集,今天我们这个A-B求的是两个集合的差,就是做集合的减法运算。(当然,大家都知道集合的定义,就是同一个集合中不会有两个相同的元素,这里还是提醒大家一下)
呵呵,很简单吧?
Input
每组输入数据占1行,每行数据的开始是2个整数n(0<=n<=100)和m(0<=m<=100),分别表示集合A和集合B的元素个数,然后紧跟着n+m个元素,前面n个元素属于集合A,其余的属于集合B. 每个元素为不超出int范围的整数,元素之间有一个空格隔开.
如果n=0并且m=0表示输入的结束,不做处理。
Output
针对每组数据输出一行数据,表示A-B的结果,如果结果为空集合,则输出“NULL”,否则从小到大输出结果,为了简化问题,每个元素后面跟一个空格.
源代码
#include
#include
#define max 3000000000
using namespace std;
main()
{
int m,n;
while(scanf("%d %d",&n,&m)!=EOF)
{
if(n0&&m0)
break;
int b[110],c[110],i,j,s,t;
long long a[110];
for(i=1;i<=n;i++)
scanf("%lld",&a[i]);
for(i=1;i<=m;i++)
scanf("%d",&b[i]);
t=n;
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
if(a[i]b[j])
{
a[i]=max;
t–;
}
}
if(t0)
printf(“NULL\n”);
else
{
if(t==1)
{
for(i=1;i<=n;i++)
if(a[i]!=max)
printf("%lld “,a[i]);
}
else
{
for(i=1;i<=n;i++)
for(j=i+1;j<=n;j++)
if(a[i]>a[j])
swap(a[i],a[j]);
for(i=1;i<=n;i++)
if(a[i]!=max)
printf(”%lld “,a[i]);
printf(”\n");
}
}
}
Problem Description M
输入一个十进制数N,将它转换成R进制数输出。
Input
输入数据包含多个测试实例,每个测试实例包含两个整数N(32位整数)和R(2<=R<=16, R<>10)。
Output
解题思路:十进制转化二进制除2取余
解题细节:①N<0时,n=0-N,按n>0走循环语句,最后输出负号 ②n>0时,b++; a[b]=n%R;n=(n-a[b])/R; n表示商,n%R表示余数 ③十六进制下输出ABCDEF④else 输出a[i]
源代码:
#include
#include
using namespace std;
int main()
{
int N,R;
while(cin>>N>>R)
{
int a[32],b=0,n;
if(N<0) n=0-N;
if(N>0) n=N;
if(N==0) cout<<“0”;
while(n>0)
{
b++;
a[b]=n%R;
n=(n-a[b])/R;
}
if(N<0) cout<<"-";
for(int i=b;i>=1;i–)
{
if(a[i]==10) cout<<“A”;
else if(a[i]==11) cout<<“B”;
else if(a[i]==12) cout<<“C”;
else if(a[i]==13) cout<<“D”;
else if(a[i]==14) cout<<“E”;
else if(a[i]==15) cout<<“F”;
else cout< }
cout<<"\n";
}
return 0;
}
Problem Description Q
古希腊数学家毕达哥拉斯在自然数研究中发现,220的所有真约数(即不是自身的约数)之和为:
1+2+4+5+10+11+20+22+44+55+110=284。
而284的所有真约数为1、2、4、71、 142,加起来恰好为220。人们对这样的数感到很惊奇,并称之为亲和数。一般地讲,如果两个数中任何一个数都是另一个数的真约数之和,则这两个数就是亲和数。
你的任务就编写一个程序,判断给定的两个数是否是亲和数
Input
输入数据第一行包含一个数M,接下有M行,每行一个实例,包含两个整数A,B; 其中 0 <= A,B <= 600000 ;
Output
对于每个测试实例,如果A和B是亲和数的话输出YES,否则输出NO。
解题思路:判断是否为亲和数即满足两个数中任何一个数都是另一个数的真约数之和
解题细节:循环中i 源代码:
#include
using namespace std;
int main()
{
int m;
cin>>m;
while(m–){
int a,b;
cin>>a>>b;
int sum1=0,sum2=0;
for(int i=1;i<=a/2;i++){
if(a%i0){
sum1+=i;
}
}
if(sum1!=b){
cout<<“NO”<
}else{
for(int j=1;j<=b/2;j++){
if(b%j
sum2+=j;
}
}
if(sum2!=a){
cout<<“NO”<
}
if(sum1b&&sum2a)
cout<<“YES”<
return 0;
}
Problem Description W
杭州人称那些傻乎乎粘嗒嗒的人为62(音:laoer)。
杭州交通管理局经常会扩充一些的士车牌照,新近出来一个好消息,以后上牌照,不再含有不吉利的数字了,这样一来,就可以消除个别的士司机和乘客的心理障碍,更安全地服务大众。
不吉利的数字为所有含有4或62的号码。例如:
62315 73418 88914
都属于不吉利号码。但是,61152虽然含有6和2,但不是62连号,所以不属于不吉利数字之列。
你的任务是,对于每次给出的一个牌照区间号,推断出交管局今次又要实际上给多少辆新的士车上牌照了。
Input
输入的都是整数对n、m(0
对于每个整数对,输出一个不含有不吉利数字的统计个数,该数值占一行位置。
解题思路:①在区间内表示各个位数的数是否为4或62 ②求车牌总数
解题细节:表示各个位数 类似的题:给定一个数,求其各个位数之和
#include
#include
using namespace std;
int main()
{ int x,n=0;
cin>>x;
int s=0;
while ( x )
{
s+=x%10;
x/=10;
n++;
}
cout< printf ( “\n” );
return 0;
}
源代码
#include
#include
using namespace std;
int main()
{
int n,m,i;
while(cin>>n>>m)
{
if(n0&&m0)
return 0;
int a,b,c,d,e,f,g,h,l,j,k,s=0,t=0,sum;
for(i=n;i<=m;i++)
{
a=i/100000;
b=(i%100000)/10000;
c=(i%10000)/1000;
d=(i%1000)/100;
e=(i%100)/10;
f=i%10;
g=i/10000;
h=(i%100000)/1000;
j=(i%10000)/100;
k=(i%1000)/10;
l=i%100;
if(a4||b4||c4||d4||e4||f4||g62||h62||j62||k62||l==62)
t+=1;
}
sum=m-n+1-t;
printf("%d\n",sum);
}
return 0;
}
Problem Description R
有一楼梯共M级,刚开始时你在第一级,若每次只能跨上一级或二级,要走上第M级,共有多少种走法?
Input
输入数据首先包含一个整数N,表示测试实例的个数,然后是N行数据,每行包含一个整数M(1<=M<=40),表示楼梯的级数。
Output
对于每个测试实例,请输出不同走法的数量
解题思路:先把前走向前三级的数据给表示出来,然后从第四个台阶开始,每一级台阶的走法,就是前两个台阶走法的加和,用循环把它给表示出来,然后输出题目所给的结果即可。
细节处理:记得每输入一组数据就要换行。
源代码:
#include
using namespace std;
int main()
{
int N,n;
int a[1000];
cin>>N;
while(N–)
{
cin>>n;
a[1]=0;
a[2]=1;
a[3]=2;
for(int i=4;i<=n;i++)
{
a[i]=a[i-1]+a[i-2];
}
cout< cout<
return 0;
}
Problem Description T
据说在很久很久以前,可怜的兔子经历了人生中最大的打击——赛跑输给乌龟后,心中郁闷,发誓要报仇雪恨,于是躲进了杭州下沙某农业园卧薪尝胆潜心修炼,终于练成了绝技,能够毫不休息得以恒定的速度(VR m/s)一直跑。兔子一直想找机会好好得教训一下乌龟,以雪前耻。
最近正值HDU举办50周年校庆,社会各大名流齐聚下沙,兔子也趁此机会向乌龟发起挑战。虽然乌龟深知获胜希望不大,不过迫于舆论压力,只能接受挑战。
比赛是设在一条笔直的道路上,长度为L米,规则很简单,谁先到达终点谁就算获胜。
无奈乌龟自从上次获胜以后,成了名龟,被一些八卦杂志称为“动物界的刘翔”,广告不断,手头也有了不少积蓄。为了能够再赢兔子,乌龟不惜花下血本买了最先进的武器——““小飞鸽"牌电动车。这辆车在有电的情况下能够以VT1 m/s的速度“飞驰”,可惜电池容量有限,每次充满电最多只能行驶C米的距离,以后就只能用脚来蹬了,乌龟用脚蹬时的速度为VT2 m/s。更过分的是,乌龟竟然在跑道上修建了很多很多(N个)的供电站,供自己给电动车充电。其中,每次充电需要花费T秒钟的时间。当然,乌龟经过一个充电站的时候可以选择去或不去充电。
比赛马上开始了,兔子和带着充满电的电动车的乌龟并列站在起跑线上。你的任务就是写个程序,判断乌龟用最佳的方案进军时,能不能赢了一直以恒定速度奔跑的兔子。
Input
本题目包含多组测试,请处理到文件结束。每个测试包括四行:
第一行是一个整数L代表跑道的总长度
第二行包含三个整数N,C,T,分别表示充电站的个数,电动车冲满电以后能行驶的距离以及每次充电所需要的时间
第三行也是三个整数VR,VT1,VT2,分别表示兔子跑步的速度,乌龟开电动车的速度,乌龟脚蹬电动车的速度
第四行包含了N(N<=100)个整数p1,p2…pn,分别表示各个充电站离跑道起点的距离,其中0
Output
当乌龟有可能赢的时候输出一行 “What a pity rabbit!”。否则输出一行"Good job,rabbit!";
题目数据保证不会出现乌龟和兔子同时到达的情况。
解题思路:应该是这个点i他前面的点 从0到 它之前即i-1 的dp值以及从这些点充满电到这点时间的和的最小值。至于为什么每个都假设充满电呢,因为对一个点有两种情况,①有剩余电量继续走不冲,②冲了再走,但是对于第
一种情况,可以认为,他之前点(如i-4~i的转移)的数据已经把他不冲给包括进去了,所以再考虑的话就重复了。
细节处理:先找到动态规划的对象,再根据特性来简化公式。注意细节,double,第一个0点不用T。
源代码:
#include
#include
#include
using namespace std;
int a[110];
double dp[110];
int main()
{
int L;
while(scanf("%d",&L)!=EOF)
{
int N,C,T;
int VR,VT1,VT2;
scanf("%d %d %d",&N,&C,&T);
scanf("%d %d %d",&VR,&VT1,&VT2);
memset(a,0,sizeof(a));
memset(dp,0,sizeof(dp));
for(int i=1; i<=N; i++)
scanf("%d",&a[i]);
a[N+1]=L;
double temp;
for(int i=1; i<=N+1; i++)
{
double min1=100000000;
for(int j=0; j {
int k=a[i]-a[j];
if(k
else
temp=(k-C)1.0/VT2+C1.0/VT1;
if(j!=0)
temp+=T;
if(min1>dp[j]+temp)
min1=dp[j]+temp;
}
dp[i]=min1;
}
printf(dp[N+1]>(L1.0/VR)?“Good job,rabbit!\n”:“What a pity rabbit!\n”);
}
return 0;
}
总结
通过进行这几天的c语言课程程序设计,自己的编程水平有了由量到质的飞跃,对学习也有自己新的感悟与思考。
⑴ 注意在这个环境中数据输入用多组数据输入(while),最后别忘了换行cout<
⑶ 寻找最简解法。如很多题中循环中i循环的次数可以减少,减少程序出错的可能。自己多尝试不同的代码,寻找最简单的代码,不要一遇到难题就想用暴力求解法编写程序,这样程序虽然AC,但自己的水平却提高得很慢。不仅要看懂别人的新思路而且需要举一反三,自己独立思考解决问题才是真理。这不仅适用于c语言,更适用于任何学科的学习和研究。
⑷ 运用abs,sqrt,ceil,floor,round,swap,sort,getchar等函数可以简单的表示问题。
⑸ 对格式要求严格:按以往的输出,在结果后面输出空格/换行,在此环境下会导致最后结果后面多输出一个空格/换行。应先输出a[1],用for循环输出a[i]。尴尬,因为这个一开始提交一直没有AC。
⑹ 像分支比较多的代码,要层次分明,理清思路,不放过一个细节,否则如果一个细节出现问题,整个程序就有可能是错误的。这样的程序要明确步骤。
⑺ 最后,感谢这几天的努力,天道酬勤,我浅浅地掌握了这门c语言,同时感恩老师平时上课的讲解与指导,我会更加努力的学习!感恩。加油。