《c++程序设计》课程设计报告
班级:数学2班 学号:2018212776
报告人姓名:刘涵
实验地点:山东农业大学东校机房411
完成起止时间:2019.1.2---2019.1.4
☆一
一,题意:
判断在给定的范围内是否存在水仙花数
二,题解:
首先题目要求输出多组数据,第二依据要求可利用取余和除法求出每个位数上的数,然后带入公式,最后在范围内如果符合则输出水仙花数,否则输出no。
三,原码:
#include<iostream>
using namespace std;
#include<math.h>
int main()
{ int m,n,l,g,k,i,a;
while(cin>>m>>n)
{ a=1;
for(i=m;i<=n;i++)
{ l=i%10;
g=i/10%10;
k=i/100;
if(i==pow(l,3)+pow(k,3)+pow(g,3))
{ if(a==1){cout<<i;a++;}
else if(a>1){cout<<" "<<i;}
}
}
if(a==1)
cout<<"no";
cout<<endl;
}
}
四,注意事项:①输入范围内无水仙花数时的处理,可利用一个变量a,初值为一,如存在水仙花数,则加一,最终通过判断a值,来表示此情况是否存在。
②可利用pow简化程序
③最后一个空格的输出:由于平台的检查输出是否正确,都是把输出内容放在文件里,然后以字符串的形式去和正确答案做对比,一直读到文件的末尾EOF,这个时候末尾多余的那些看不见的字符就会被读出来,然后发现输出和正确答案不同,得出PE!!!
④if else if 的使用
if(条件..1){
要执行的语句;
}
if(条件..2){
要执行的语句
}
双if是每一个if都会进行判断,依次对if进行判断,互相之间不会影响;
if(条件..1){
执行的语句
}else if(条件..2){
执行的语句
}
这个if和else if 之间是有联系的,当不满足if中的条件的时候,就会去执行else if ,如果if中的条件已经满足了,就不会去判断else if中的条件了
☆二
题意:
判断表达式的值是否都为素数。
题解:
首先输入多组样例,再带入公式计算结果,接着判断结果是否为素数,最后利用变量a的值判断是否范围内的值均为素数。
原码:
#include<iostream>
#include<math.h>
using namespace std;
int main()
{ int x,y,n,i,a,t;
while(cin>>x>>y)
{ if(x==0&&y==0)
break;
else
{ a=0;
for(n=x;n<=y;n++)
{t=n*n+n+41;
for(i=2;i<=sqrt(t);i++)
{if(t%i==0)
a++;
}
}
} if(a==0)
cout<<"OK"<<endl;
else
cout<<"Sorry"<<endl;
}
}
注意事项:
①素数的判断:若从2到sqrt(t)-1的数均不可整除t,那t即为素数
☆三
题意:
计算特殊多项式之和
题解:
相加的思想很简单,但细节很重要
原码:
#include<stdio.h>
#include<iostream>
using namespace std;
#include<math.h>
int main()
{ int m,n,i,j;
double s;
cin>>m;
for(i=1;i<=m;i++)
{cin>>n;s=0;
for(j=1;j<=n;j++)
{s+=1/(j*1.0)*(pow(-1,j+1));}
printf("%.2lf\n",s);
}
}
注意事项:
①当1/j时,要对j先乘于一个1.0,以实现整型数到实型数的变换
②对多项式每一项前正负号的描述,利用pow(-1,j+1)
☆四
题意:
求一个平均值序列,分两种情形
题解:
分两步做,先对前几项,符合可被m整除的,控制每m项求一个平均值,最后对有余项取平均值
原码:
#include<iostream>
using namespace std;
int main()
{ int s,i,j,n,m;
double y,x;
while(cin>>n>>m)
{
for(i=1;i<=(n/m);i++)
{x=y=0;
for(j=((i-1)*m+1);j<=((i-1)*m+m);j++)
{x+=(2*j);}
y=x*1.0/m;
if(n%m!=0)
cout<<y<<" ";
else
{if(i==1)
cout<<y;
else if(i!=1)
cout<<" "<<y;
}
}s=0;
if(n%m!=0)
{for(i=(n-n%m+1);i<=n;i++)
{s+=2*i;}
cout<<s;
}
cout<<endl;
}
}
注意事项:
①利用i j实现对前n/m个m项求平均值时,注意起始与终止值
②偶数列的表示 {x+=(2*j);}
③x,y变量要定义为double
☆五
题意:
将输入的数按绝对值从小到大的顺序输出
题解:
依次通过两两比较将绝对值小的数往后放
原码:
#include<iostream>
using namespace std;
#include<cmath>
int main()
{
int n,i,j,t,a[105];
while(cin>>n)
{ if(n==0)
break;
else
{ for(i=0;i<n;i++)
{cin>>a[i];}
for(j=1;j<n;j++)
{ for(i=0;i<(n-j);i++)
{ if(abs(a[i])<abs(a[i+1]))
{swap(a[i],a[i+1]);}
}
}
for(i=0;i<n-1;i++)
{cout<<a[i]<<" ";}
cout<<a[n-1]<<endl;
}
} return 0;
}
注意事项:
①swap的使用,简化程序
②i与j的配合,使得每两个数进行比较
③最后一个输出的值后不要有空格
④abs为整数取绝对值,可对应cstdlib
☆六
题意:
将一个数插入有序数列
题解:首先考虑特殊情况,如果x小于a[i],那么即令a[n]每个向后退一格,然后再表示普通情况,大于x的a[n]每个向后退一格
原码:
#include<iostream>
using namespace std;
int main()
{
int n,l,i,j,m,a[105];
while(cin>>n>>m)
{ if(m==0&&n==0)
exit(0);
else
{for(i=0;i<n;i++)
{cin>>a[i];}
if(m<a[0])
{
for(i=n;i>0;i--)
{a[i]=a[i-1];}
a[0]=m;
}
else
{for(i=n-1;i>=0;i--)
{if(m>a[i])
{l=(i+1);break;}
}
for(j=n;j>l;j--)
{a[j]=a[j-1];}
a[l]=m;
}for(i=0;i<n;i++)
{cout<<a[i]<<" ";}
cout<<a[n];
}cout<<endl;
}
}
注意事项:①将大于x的a[n]赋值给a[n+1],会出错;故可让j从n开始,向前赋值,从而避免出错
②最后一项后无空格
☆七
题意:
杭电老师发工资
题解:
按可使给每个老师的工资均无需找零,且所发张数最少,应从面额最大的100开始整除工资数,再取余,用50除于余额,依次向下进行
原码:
#include<iostream>
using namespace std;
int main()
{
int n,a[100],x,t,f,g,y,l,k,e,h,i;
while(cin>>n)
{
if(n==0)
break;
else
{
for(i=0;i<n;i++)
{
cin>>a[i];
} h=0;
for(i=0;i<n;i++)
{t=a[i]/100;
f=a[i]%100/50;
g=a[i]%100%50/10;
y=a[i]%100%50%10/5;
l=a[i]%100%50%10%5/2;
k=a[i]%100%50%10%5%2;
e=t+f+g+y+l+k;
h=h+e;
}
cout<<h<<endl;
}
}
}
注意事项:①只要细心输入整除及取余即可
☆八
题意:
两个时间的相加
题解:
运用好选择结构,从秒开始相加,同时注意每到六十便向上一位进一
原码:
#include<iostream>
using namespace std;
int main()
{
double AH,AM,AS,BH,BM,BS,N,i;
cin>>N;
for(i=0;i<N;i++)
{cin>>AH>>AM>>AS>>BH>>BM>>BS;
if((AS+BS)>59)
{
if((AM+BM+1)>59)
cout<<(AH+BH+1)<<" "<<(AM+BM-59)<<" "<<(AS+BS-60)<<endl;
else
cout<<(AH+BH)<<" "<<(AM+BM+1)<<" "<<(AS+BS-60)<<endl;
}
else
{ if((AM+BM)>59)
cout<<(AH+BH+1)<<" "<<AM+BM-60<<" "<<AS+BS<<endl;
else
cout<<AH+BH<<" "<<AM+BM<<" "<<AS+BS<<endl;
}
}
}
☆九
题意:
求手机号的短号
题解:
利用整除取余获得手机号的后五位,然后加上600000
原码:
#include<iostream>
#include<math.h>
using namespace std;
int main()
{ int N,i,y;
long long int a[201];
cin>>N;
for(i=0;i<N;i++)
{cin>>a[i];}
for(i=0;i<N;i++)
{y=6*pow(10,5)+a[i]%10+((a[i]/10)%10)*10+((a[i]/100)%10)*100+((a[i]/1000)%10)*1000+((a[i]/10000)%10)*10000;
cout<<y<<endl;
}
}
注意事项:值得注意的是long long int的使用,很容易让人忽略,而若不注意,则会出现乱输出
☆十
题意:排除不吉利数字
题解:将含有4,62的号码剔除,通过取余判断每一位是否为4,或每两位是否为62,另外在本题中我应用了预处理的方法,有些暴力但因为在时间限制内,也十分管用,就是略显麻烦。其实最好令i从n到m循环,使程序更简洁
原码:
#include<iostream>
using namespace std;
int a[1000000]={0};
int main()
{
int n,m,i,t=0;
for(i=1;i<1000000;i++)
{
if(i%10==4||i/10%10==4||i/100%10==4||i/1000%10==4||i/10000%10==4||i/100000%10==4)
t+=0;
else if(i%100==62||i/10%100==62||i/100%100==62||i/1000%100==62||i/100000%1000==62)
t+=0;
else
t++;
a[i]=a[i]+t;
}
while (cin>>n>>m)
{ if(n==0&&m==0)
break;
else
{cout<<(a[m]-a[n-1])<<endl;}
}}
注意事项:对含有4或 62的数做假循环t+=0;这样可排除使用该条件的真循环出现重复计数
☆十一
题意:
判断给定的n m是否分别为两数之和,两数之积
题解:
原本想通过判断if(i+j==n&&i*j==m)解决,可这样会Output limited exceeded,也就是说有可能排除不了多余情况的输出。故我通过解两元方程的方法,将循环减少一重,且通过变量a的值控制单次输出,简化了程序。
原码:
#include<iostream>
#include<math.h>
using namespace std;
int main()
{
int n,m,i,j,a;
while(cin>>n>>m)
{if(n==0&&m==0)
break;
else
{ a=0;
for(i=-99;i<100;i++)
{if(i*i-i*n+m==0&&a==0)
{a++;cout<<"Yes"<<endl;}
}
if(a==0)
cout<<"No"<<endl;
}
}}
注意事项:if(i*i-i*n+m==0&&a==0)中a的使用,避免了不必要输出
☆十二
题意:
判断是否为SKY数
题解:
根据进制转化,将数值除16或12取余,再令其余数除16或12取余,依次向下进行
原码:
#include<iostream>
#include<math.h>
using namespace std;
int main()
{
int n,t,k,s,d,g;
while(cin>>n)
{ d=n;g=n;
if(n==0) break;
else
{
s=n%10+n/10%10+n/100%10+n/1000;
t=k=0;
while(d!=0)
{
t+=d%16;
d=d/16;
}
while(g!=0)
{
k+=g%12;
g=g/12;
}
} if(s==t&&s==k)
cout<<n<<" is a Sky Number."<<endl;
else
cout<<n<<" is not a Sky Number."<<endl;
}
}
注意事项:将t=k=0;放在else条件内,使其尽量挨着与其相关的执行语句,避免出现乱输入
☆十三
题意:
A的B次方
题解:显然若1000的1000次方连long long int也无效了,于是想到其实A的B次方的后三位与前边的几位数并无关,这样问题就简化了
原码:
#include<iostream>
#include<math.h>
using namespace std;
int main()
{ int A,B,t,i;
while(cin>>A>>B)
{
if(A==0&&B==0)
break;
else
{ t=1;
for(i=1;i<=B;i++)
{ t=(t*A)%1000;
}
} cout<<t<<endl;
}
}
注意事项: t=(t*A)%1000;的使用让程序简化
☆十四
题意:
M阶台阶的走法
题解:与前面一题,和后边一题类似,推导公式
原码:
#include<iostream>
using namespace std;
int main()
{ int N,M,i,k,a[42];
cin>>N;
for(k=1;k<=N;k++)
{cin>>M;
a[2]=1;
a[3]=2;
a[1]=0;
if(M>3)
{for(i=4;i<=M;i++)
a[i]=a[i-1]+a[i-2];
} cout<<a[M]<<endl;
}
}
注意事项:①初始时是在第一阶
②最后输出a[M],输出a[i]无结果
③前几阶无规律的单独列出
☆十五
题意:
计算集合A-B
题解:
即比较A与B中的元素,把A中含有的B中也有的元素去掉,我采用将这样的A中的元素付给他一个超范围值,没想到其他方法,但这样却十分省时间
原码:
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
int main()
{ int n,m,i,j,a[101],b[101],s;
while(cin>>n>>m)
{
if(n==0&&m==0)
exit(0);
else
{ for(i=0;i<n;i++)
cin>>a[i];
for(j=0;j<m;j++)
cin>>b[j];
sort(a,a+n);s=0;
for(i=0;i<n;i++)
{for(j=0;j<m;j++)
{ if(a[i]==b[j])
{
a[i]=pow(10,8);
s++;
}
}if(a[i]!=pow(10,8))
cout<<a[i]<<" ";
}
if(s==n)
cout<<"NULL";
}cout<<endl;
}
}
注意事项:超范围值一定要真的超范围
总结:
每个题都不能轻易判断其简单或困难,或者说无论题难题简单,都应认真应对,会做的要做对,不会的不到最后绝不放弃。虽然课程结束了,自己也没做的多好,但通过本次活动,仍有很多收获,比如凡事需细心,不要少做,不要只顾头不顾尾,像是好多题中最后一个空格的不必要输出问题。还有,当周围有人在躁动,自己也要学会冷静下来,这对考试时是有很大帮助的,这也是我一直需要改变的,我想通过这次活动,我改变了不少。