课程设计实验报告

《c++程序设计》课程设计报告
题目一:

来源:设一
1002 Problem B

题目简述:“水仙花数”是指一个三位数,它的各位数字的立方和等于其本身,比如:153=13+53+3^3。输入数据有多组,每组占一行,包括两个整数m和n(100<=m<=n<=999)。输出的水仙花数必须大于等于m,并且小于等于n,如果有多个,则要求从小到大排列在一行内输出,之间用一个空格隔开;

如果给定的范围内不存在水仙花数,则输出no。

解题思路:判断水仙花数,在一个循环里,将区间内的每个数逐一判断,利用余数分离每一位数,进行判断即可。(较简单)

代码及部分说明:

#include<stdio.h>

main()

{

int m,n,i,a,b,c,s=0;

while(scanf("%d
%d",&m,&n)!=EOF)

{

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

{

a=i/100;

b=(i%100)/10;

c=i%10;

if(aaa+bbb+ccc==i)

{

s+=1;

if(s==1)

printf("%d",i);

if(s!=1)

printf(" %d",i);

}

}

if(s==0)

printf(“no”);

printf("\n");

s=0;

}

return
0;

}

#include

using
namespace std;

int
main()

{

int m,n,i,a,b,c,s=0;

while(cin>>m>>n)

     {

         if(m==0&&n&&0)

         break;

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

             {

                  a=i/100;

                  b=(i%100)/10;

                  c=i%10;

                  if(a*a*a+b*b*b+c*c*c==i)

{

s+=1;

if(s==1)

cout<<i; if(s!=1)

cout<<"

"<<i;

}

}

if(s==0)

cout<<"no";

cout<<endl;

s=0;

     }

return
0;

}

对于蓝色区域:输出的格式问题:先判断输出数据的个数,大于一的时候先输出一个,后面的其他数据就先输空格,再输数据,格式就不会出错了。

题目二:

来源:设一
1004 Problem D

题目简述:表达式n^2+n+41,当n在(x,y)范围内取整数值时(包括x,y)(-39<=x<y<=50),判定该表达式的值是否都为素数。对于每个给定范围内的取值,如果表达式的值都为素数,则输出"OK",否则请输出“Sorry”。

解题思路:先自定义一个函数,用来判断素数。主函数内,借助布尔数组判断结果。循环内,每算出一个结果,就进行判断,只有全部是素数时,借助布尔变量输出OK即可。(较简单)

代码及部分说明:

#include

#include

using
namespace std;

int prime(int
a)

{

for(int i=2;i<=sqrt(a);i++)        

{           


    if(a%i==0)            

    return 0;        

}    

return 1;

}

int
main()

{

int x,y,m=0;    

bool c[100]={true};    

while(cin>>x>>y,!(x0&&y0))

{    

    m=0;c[1]=true;

    for(int i=1;i<=100;i++)

    {

    m=x*x+x+41;

    if(prime(m)==0)

      {

c[1]=false;break;

      }

    if(x==y)break;x++;

    }

if(c[1]==false)      

cout<<“Sorry”<<endl;

elsecout<<“OK”<<endl;

}

return 0;

}

蓝色部分是对每一个结果的判断,注意要有严密的逻辑思维,可以先在纸演示一下。

绿色部分就是利用布尔变量进行的输出,要学会这种方法。

题目三:

来源:设一
1006 Problem F

题目简述:定义从2开始的递增长度为n(n<=100)的数列,按照顺序每m个数求出一个平均值,如果最后不足m个,则以实际数量求平均值。编程输出该平均值序列。输入数据有多组,包含两个正整数n和m,输出一个平均值序列,每组输出占一行。

解题思路:利用while将数据输入,先假设最后不足m个,将能正好处理的个数和剩余数据的个数算出,利用这两个算出的结果进行后续的平均值处理,处理过程中的情况较多,if语句的选择就比较好用,但一定要分析全面。(一般)

代码及部分说明:

#include

using
namespace std;

int
main()

{

int n,m,i,j,k,sum=0,ave=1,p,q,w,e=0;

while(cin>>n>>m)

{

    e=0;

    p=n/m;

    q=n%m;

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

    {

        sum=0;

        if(i==1)

        {

            for(j=2;j<=2*m;j+=2)

            {sum+=j;}

            ave=sum/m;

            if(e==0)

cout<<ave;

            else cout<<"

"<<ave;

            e++;

            w=j;

        }

        else

        {

            for(k=w;k<2*m+w;k+=2)

            {sum+=k;}

            ave=sum/m;

            cout<<"

"<<ave;

            w=k;

        }

    }

    ave=1;

    if(q==0)

    {cout<<endl;}

    else

    {

        sum=0;

        for(i=w;i<q*2+w;i+=2)

        {sum+=i;}

        ave=sum/q;

        cout<<"

"<<ave;

        cout<<endl;

    }

}

return 0;

}

绿色部分的处理是关键,有效简便了思考过程,不过比较繁琐。

黄色部分还是对输出格式的处理,与第一个类似。

题目四:

来源:设一
1008 Problem H

题目简述:有一头母牛,它每年年初生一头小母牛。每头小母牛从第四个年头开始,每年年初也生一头小母牛。输入数据由多个测试实例组成,每个测试实例占一行,包括一个整数n(0<n<55),对于每个测试实例,输出在第n年的时候母牛的数量。

解题思路:典型的斐波那契额数列变形题,先找规律,从第一个,第二个,第三个找出,可以通过递推,循环即可;或者是通过数组赋值,每一个下标对应一个数,需要时调用输出即可。(难度一般)

代码及部分说明:

#include

using
namespace std;

int
main()

{

int n,a1=1,a2=2,a3=3,m=0;

while(cin>>n,n!=0)

  { 

       if(n==1)

cout<<a1<<endl;

       if(n==2)

cout<<a2<<endl;

       if(n==3)

cout<<a3<<endl;

       if(n>3)

      {

       m=0;a1=1;a2=2;a3=3;

       for(int i=4;i<=n;i++)

          {

              m=a1+a3;

              a1=a2;

              a2=a3;

              a3=m;

          }

       cout<<m<<endl;

   }

   }

return 0;

}

红色部分是对刚开始的赋值,便于后续的计算递推用。

绿色部分是递推关系,值得注意的是,每次大循环之前一定要对前几个值进行恢复,否则会输出错误(因为会累加)。

题目五:

来源:设一
1009 Problem I

题目简述:输入n(n<=100)个整数,按照绝对值从大到小排序后输出。
输入数据有多组,每组占一行,每行的第一个数字为n,接着是n个整数,n=0表示输入数据的结束,不做处理。 输出排序后的结果,两个数之间用一个空格隔开,各占一行。

解题思路:定义一个数组,然后直接循环赋值,之后用swap函数,先用if判断大小,用abs函数,直接在swap内判断即可,无需引入多于变量。之前用了一种比较麻烦的方法,想定义两个数组,a为原数,b为取绝对值之后的数,sort排序,再更换下标输出,后来经过判断,方法行不通,故作罢。(较简单)

代码及部分说明:

#include

#include<stdlib.h>

#include

using
namespace std;

int
main()

{

int a[105],n;

while(cin>>n,!(n==0))

{

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

    {

        cin>>a[i];

    }

    for(int j=n-1;j>=1;j--)

    {

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

    {

        if(i==n)

        break;

        if(abs(a[i])<abs(a[i+1]))

swap(a[i],a[i+1]);

    }

    }

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

    {

        if(i!=n)

        cout<<a[i]<<"

";

        if(i==n)

        cout<<a[i];

    }

    cout<<endl;

}

return 0;

}

绿色部分为主干部分,先判断绝对值大小,再决定是否交换,值得学习。

题目六:

来源:设一
10013 Problem M

题目简述:输入一个十进制数N,将它转换成R进制数输出。包含两个整数N(32位整数)和R(2<=R<=16,
R<>10),输出转换后的数,每个输出占一行。

解题思路:借助函数进行操作。构造函数,与现实中相同,用几进制就除以几,每一次的商正序存放在数组中,完成后再倒序输出。需要注意的是大于10的进制,定义一个包含A-F的字符型数组,if判断如果大于十,利用循环输出字母即完成工作。(一般)

代码及部分说明:

#include

#include<stdio.h>

#include

using
namespace std;

void
td(int n,int a);

char
ch[6]={‘A’,‘B’,‘C’,‘D’,‘E’,‘F’};

int
main()

{

int n,m;

while(scanf("%d",&n)!=EOF)

{

    cin>>m;

    td(n,m);

}

return 0;

}

void
td(int n,int a)

{

int

x[17],i,j,k=0;

if(n<0)

cout<<"-";

j=abs(n);

do

{

    k++;

    i=j%a;

    j/=a;

    x[k]=i;

} while(j!=0);

for(int

h=k;h>=1;h–)

{

    if(x[h]<10)

    cout<<x[h];

    else

cout<<ch[x[h]-10];

}

cout<<endl;

}

蓝色部分是除数和存储,以便后面输出利用。

绿色部分是自定义函数的重中之重,巧妙的构思值得大家学习与借鉴。

题目七:

来源:设一
10015 Problem O

题目简述:求两个集合的差,每组输入数据占1行,每行数据的开始是2个整数n(0<=n<=100)和m(0<=m<=100),分别表示集合A和集合B的元素个数,然后紧跟着n+m个元素,前面n个元素属于集合A,其余的属于集合B. 每个元素为不超出int范围的整数,如果n=0并且m=0表示输入的结束,每组数据输出一行数据,表示A-B的结果,如果结果为空集合,则输出“NULL”,否则从小到大输出结果。

解题思路:首先是定义两个数组,赋值两个集合。然后利用双重循环判断重复的数,将其赋值为零,sort排序。最后循环加判断,引入一个变量看是否为空集,输出即可。(中等)

代码及部分说明:

#include

#include

int
a[105],b[105];

using
namespace std;

int
main()

{

int

m,n,i,j,k;

while(cin>>n>>m,!(n0&&m0))

{

    k=0;

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

    cin>>a[i];

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

    cin>>b[j];

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

       {

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

           {

if(b[i]==a[j])

           a[j]=0;

           }

       }

    sort(a,a+n+1);

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

    {

        if(a[i]!=0)

        {

cout<<a[i]<<" ";

            k++;

        }

    }

    if(k==0)

cout<<“NULL”;

    cout<<endl;

}

return 0;

}

蓝色部分为作差,将相同的去除。

绿色部分为输出且判断是否为空集。

黄色部分利用变量看是否为空集,输出。

题目八:

来源:设一
10016 Problem P

题目简述:求A^B的最后三位数表示的整数。输入数据包含多个测试实例,每个实例占一行,由两个正整数A和B组成(1<=A,B<=10000),如果A=0, B=0,则表示输入数据的结束, 对于每个测试实例,请输出A^B的最后三位表示的整数,每个输出占一行。

解题思路:对于一般的数可以操作,十分简便,将后三位分离即可。而对于超内存的数则需要谨慎,只保留后三位即可,前面的位数一概舍去,只进行后三位的处理即可。(中等)

代码及部分说明:

#include

using
namespace std;

int
main()

{

long long int a,b,i;

while(cin>>a>>b,!(a0&&b0))

{

    long long int s=1;

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

    s=(s*a)%1000;

    cout<<s<<endl;

}

return 0;

}

红色部分即为仅仅后三位的处理,代码简单,但不太好想。

题目九:

来源:设一
10019 Problem S

题目简述:有一只经过训练的蜜蜂只能爬向右侧相邻的蜂房,不能反向爬行.计算蜜蜂从蜂房a爬到蜂房b的可能路线数。蜂房的结构如下所示。

输入数据的第一行是一个整数N,表示测试实例的个数,然后是N 行数据,每行包含两个整数a和b(0<a<b<50)。对于每个测试实例,请输出蜜蜂从蜂房a爬到蜂房b的可能路线数,每个实例的输出占一行。

解题思路:此题也是斐波那契数列变形,但要注意与之前奶牛与爬楼梯的区别,思路是自我演算出前几项的结果,递推时要注意循环的次数,比较难想,但也不困难,熟能生巧。(一般)

代码及部分说明:

#include

using
namespace std;

int
main()

{

long long int n,a,b,i,a1,a2,a3,m=0;

cin>>n;

while(n--)

{

    cin>>a>>b;

    if((b-a)==1)

cout<<“1”<<endl;

    if((b-a)==2)

cout<<“2”<<endl;

    if((b-a)==3)

cout<<“3”<<endl;

    if((b-a)>3)

    {

         a1=1,a2=2,a3=3,m=0;

for(i=3;i<(b-a);i++)

            {

                 m=a2+a3;

                 a2=a3;

                 a3=m;

            }

         cout<<m<<endl;

    }

}

return 0;

}

蓝色部分为自我演算得出的答案,需要仔细。

绿色部分为每次初始赋值和循环次数的判定。

题目十:

来源:设一
10022 Problem V

题目简述:方程:Ai = (Ai-1 + Ai+1)/2 - Ci
(i = 1, 2, 3, … n),给出A0,
An+1, 和
C1, C2, …Cn.计算A1 输入多个测试数据,对于每组数据,先是一个正整数n,(n <= 3000); 然后是2个数a0, an+1.接下来的n行每行有一个数ci(i = 1,
…n);以文件结束符结束。对于每个测试实例,用一行输出所求得的a1(保留2位小数)。

解题思路:对于这种数列的问题,一定要先在纸面上演算,将通项公式推出,得到规律,每一项系数的分母都为(n+1),在最后输出的时候统一处理除(n+1)。对给出的常数系数进行循环处理,循环加和,最后减去即可。(需要数学功底,难度略大)

代码及部分说明:

#include

#include

using namespace
std;

int
main()

{

double a[3500],c[3500];

int n,i,j;

double b,s;

b=0.00,s=0.00;

while(cin>>n)

{

    j=n;

    cin>>a[0]>>a[n+1];

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

    cin>>c[i];

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

    {

    s=s+j*c[i];

    j--;

    }

    b=(n*a[0]+a[n+1]-s*2)/(n+1);

cout<<fixed<<setprecision(2)<<b<<endl;

    s=0.00;

}

return 0;

}

蓝色部分为对c常数部分的系数处理,循环累加。

绿色部分为对结果的处理,直接输出结果即可。

题目十一:

来源:设二
1003 Problem C

题目简述:在一个平面内有两个点,求两个点分别和原点的连线的夹角的大小。夹角的范围[0,180],两个点不会在圆心出现。输入数据的第一行是一个数据T,表示有T组数据。每组数据有四个实数x1,y1,x2,y2分别表示两个点的坐标,这些实数的范围是

[-10000,10000]。对于每组输入数据,输出夹角的大小精确到小数点后两位。

解题思路:同样是数学,需要用数学函数的处理,用开根号是算边长,然后用余弦定理算出cos夹角的值,再用反余弦函数得到带Π的值,但要注意的是将Π除去,再乘以180,最后保持两位小数输出即可。(一般)

代码及部分说明:

#include

#include

#include

#include

using namespace std;

int main()

{

int t,i;

double a,b,c,d,m,n,o,l,p;

cin>>t;

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

{

cin>>a>>b>>c>>d;

    m=0.00,n=0.00,o=0.00,l=0.00,p=0.00;

    m=sqrt(a*a+b*b);

    n=sqrt(c*c+d*d);

    o=sqrt((a-c)*(a-c)+(b-d)*(b-d));

    l=(m*m+n*n-o*o)/(2*m*n);

    p=acos(l)*180/3.1415926;

    cout<<fixed<<setprecision(2)<<p<<endl;

}

return 0;

}

蓝色部分为两点之间的距离公式。

绿色部分为余弦定理公式。黄色部分为对结果的处理,十分关键,这是一细节处理。

题目十二:

来源:设二
1004 Problem D

题目简述: 一整数,知道前几位,不知道末二位,被另一个整数除尽了,求该数的末二位,输入数据有若干组,每组数据包含二个整数a,b(0<a<10000,10<b<100),遇到0 0则结束。 对每组数据,将满足条件的所有尾数在一行内输出,同组数据的输出,其每个尾数之间空一格,行末没有空格。

解题思路:先将整数扩大一百倍,再除已另一个整数得余数,后两位从0判断到99,但要注意个位数的输出,前面要加零。这就需要if加判断,这是其一;另外要注意输出的空格处理,同样就用if处理。最后就是if考虑的情况,一定要全面。(一般)

代码及部分说明:

#include

using
namespace std;

int
main()

{

int a,b,c,i,z;

while(cin>>a>>b)

{

    if(a==0&&b==0)

    {

       break;

       }

       z=0;

    c=a*100;

    for(i=0;i<=99;i++)

    {

       if((c+i)%b==0)

        {

            z++;

            if(z==1&&i>9)

cout<<i;

            if(z==1&&i>=0&&i<=9)

cout<<“0”<<i;

            if(z>1)

{if(i>9)

cout<<" "<<i;

            if(i>=0&&i<=9)

cout<<" "<<“0”<<i;

            }

            

        }

    }

    cout<<endl;

}

return 0;

}

绿色部分为对空格输出的处理,蓝色部分为对输出个位数的处理,但考虑要全面。

题目十三:

来源:设二
1005 Problem E

题目简述: 把一个偶数拆成两个不同素数的和,有几种拆法。输入包含一些正的偶数,其值不会超过10000,个数不会超过500,若遇0,则结束。对应每个偶数,输出其拆成不同素数的个数,每个结果占一行。

解题思路:先定义一个判断素数函数供主函数判断用。在利用循环两边向中间逼近,用if判断是否符合条件输出。(中等)

代码及部分说明:

#include

using namespace std;

bool prime(int n)

{

if(n2 || n3)

return 1;

if(n%6!=1 && n%6!=5)

return 0;

for( int i=5;i*i<=n;i=i+6)

{

if(n%i==0 || n%(i+2)==0)

return 0;

}

return 1;

}

int main()

{

int n,i,t;

while(cin>>n)

{

t=0;

if(n==0)

{

        return 0;

}

for(i=2;i<=n/2;i++)

{

if(prime(i)==1 && prime(n-i)==1
&& i!=n-i)

t++;

}

cout<<t<<endl;

}

}

红色部分即为两个素数相加是否为原数的判断,值得学习。

题目十四:

来源:设二
1006 Problem F

题目简述:一种有趣的四位数2992,它的十进制数表示,其四位数字之和为2+9+9+2=22,它的十六进制数BB0,其四位数字之和也为22,同时它的十二进制数表示1894,其四位数字之和也为22。输入含有一些四位正整数,如果为0,则输入结束。若n为Sky数,则输出“#n is a Sky Number.”,否则输出“#n
is not a Sky Number.”。

解题思路:输入一个数,同纸上演算一样,分别用十,十二,十六除以这个数,分别加和,然后进行比较即可。(一般)

代码及部分说明:

#include

using namespace std;

int main()

{

int
n,i,a,b,c,d,e,f,g,h,j;

while(cin>>n)

{

if(n==0)

break;

g=n;h=n,j=n;

a=0,b=0;

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

{

a=n%10;

n=n/10;

b=b+a;

}

//cout<<b<<endl;

c=0,d=0;

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

{

c=h%12;

h=h/12;

d=d+c;

}

//cout<<d<<endl;

e=0,f=0;

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

{

e=j%16;

j=j/16;

f=f+e;

}

//cout<<f<<endl;

if(bd&&df)

cout<<g<<" is a Sky
Number."<<endl;

else cout<<g<<" is
not a Sky Number."<<endl;

}

return 0;

}

红色部分一定要在进入循环之前赋0。

蓝色部分即为输入的数,由于中间有处理,故这个数需要保存。

题目十五:

来源:设二
1008 Problem H

题目简述:三角形,每行包含一个字符和一个整数n(0<n<41),不同的字符表示不同的花纹,整数n表示等腰三角形的高。显然其底边长为2n-1。如果遇到@字符,则表示所做出来的样板三角形已经够了。每个样板三角形之间应空上一行,三角形的中间为空。显然行末没有多余的空格。

解题思路:三角形,先判断前一个是否输出完一个三角形,换行。

然后利用循环进行三角形的输出(与oj中矩形和菱形类似)(一般)

代码及部分说明:

#include

#include

using
namespace std;

int
main()

{

int n,s;

char a;

s=0;

while(cin>>a)

{

    s++;

    if(a=='@')

    break;

    else

    {

        cin>>n;

        if(s>1)

cout<<endl;

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

{

for(int

j=1;j<=2*n-1;j++)

  {

    if(i+j==n+1||i==n||j-i==n-1)

    cout<<a;

if(i+j!=n+1&&i<n&&j-i<n-1)

    cout<<"

";

  }

cout<<endl;

    }

}

}

return 0;

}

红色为循环的结束;蓝色为一个三角形的输出完了,换行;绿色三角形的输出,加强理解即可。

总结:经过三天的程序设计实验,一学期学到的知识得到充分的提炼和总结,运用知识的能力得到显著提升。程序语言解决问题的方法从无到有,愈发的熟练,但还是有一些问题头绪很乱或者是无头绪;一方面是现实中无法用所学知识解决,从而无法用程序语言写出;另一方面是现实中解决出来,但还不会用程序语言写出来。对于过去的时间,所学知识还要熟练应用;以后的时间如果还想进一步提升就只能靠自学,将语言其他部分全部学会,这样程序就会更简单,快捷。最后,革命尚未成功,同志仍需努力。

猜你喜欢

转载自blog.csdn.net/qq_27094167/article/details/85846957