C++总结报告

    经过大约一周的时间,程序设计A课程逐渐接近了尾声。下面将介绍一下心得。
    T1:输入一个百分制的成绩t,将其转换成对应的等级。这道题并不难,我们只需要利用条件语句if就能轻而易举的完成这道题。另外,作为第一题,这道题并没有出现所谓的陷阱。下面让我们看一下源代码: #include<iostream>using namespace std;int main(){    int a;    while(cin >>a)    {        if(a>=90&&a<=100)        cout <<'A'<<endl;        else if(a>=80&&a<=89)        cout <<'B'<<endl;        else if(a>=70&&a<=79)        cout <<'C'<<endl;        else if(a>=60&&a<=69)        cout <<'D'<<endl;        else if(a>=0&&a<=59)        cout <<'E'<<endl;        else cout <<"Score is error!"<<endl;        }
    T2: “水仙花数”是指一个三位数,它的各位数字的立方和等于其本身,比如:153=1^3+5^3+3^3。现在要求输出所有在m和n范围内的水仙花数。
    这道题也是一道简单题,我们只需将这个三位数的每一位单独取出来,然后代入公式进行判断就可以了,在解题上并无难处。不过,这道题却是有一个坑:在最后一个水仙花数找到并输出后,不能有空格跟在后面,正是这一点在我做题是卡了我一下。不过并不是什么困难的问题。原代码如下:#include<iostream>using namespace std;int main(){    int m,n,a,b,c,d=0,e;    while(cin >>m>>n)    {        e=1;        d=0;        for(int i=m;i<=n;i++)        {            a=i%10;            b=i/10%10;            c=i/100%10;            if(i==a*a*a+b*b*b+c*c*c)            {                if(e==1)            cout <<i;            else cout <<' '<<i;            e++;            }            else d++;            }            if(d==n-m+1)            cout <<"no"<<endl;            else cout <<endl;            }} 
    T3:对于表达式n^2+n+41,当n在(x,y)范围内取整数值时(包括x,y)(-39<=x<y<=50),判定该表达式的值是否都为素数。 
    这道题关键在于如何判断【x,y】内所有数是否为素数以及如何判断素数。首先我们要知道,何为素数?素数即除1和自己外无其他因数。因而在判断n时要从2判断到n-1,但实际上,我们还可以进行优化,只需从2判断到sqrt(n)即可。如何判断所有的数呢?下面我们看代码:#include<iostream>#include<math.h>using namespace std;int main(){    int m,n,a,b;    while(cin >>m>>n)    {        if(m==0&&n==0)        break;        b=0;        for(int i=m;i<=n;i++)        {            a=i*i+i+41;            for(int j=2;j<=sqrt(a);j++)            {                if(a%j==0)                b++;                }}                if(b==0)                cout <<"OK"<<endl;                else cout <<"Sorry"<<endl;                }} 
    不难看出,我运用了b这个细节,本质上b的用法和bool型变量是一致的(只是我不会用后者)。当出现一个数不为素数时,b的值会加1,判断结束后,只要b不等于0,说明这一组数不全是素数。
     T4:有一个长度为n(n<=100)的数列,该数列定义为从2开始的递增有序偶数,现在要求你按照顺序每m个数求出一个平均值,如果最后不足m个,则以实际数量求平均值。编程输出该平均值序列。 
     个人认为,这个题还是有一定的难度的。至少我是思考了一整天才理清了思路。如果n可以被m整除,那么我们只需每m个数求一个平均数;不能整除,我们依旧可以先求出可以被整除的那一部分,对于最后不能被整除的部分,单独进行考虑。因而我们可以将问题分为三类进行解决。代码如下:#include<iostream>using namespace std;int a[101];int main(){    int n,m,sum=0,average=0,b;    while(cin >>n>>m)    {        if(n%m==0)        {            for(int i=1;i<=n;i++)            {                a[i]=2*i;                sum+=a[i];                average=sum/m;                if(i%m==0)                {                    if(i!=n)                    {                        cout <<average<<' ';                        sum=0;average=0;}                        else                        { cout <<average<<endl;sum=0;average=0;}                    }}}        else        {            b=n/m;            for(int i=1;i<=b*m;i++)            {                a[i]=2*i;                sum+=a[i];                average=sum/m;                if(i%m==0)                {                    cout <<average<<' ';                    sum=0;average=0;                    }}                    for(int i=b*m+1;i<=n;i++)                    {                        a[i]=2*i;                        sum+=a[i];                        average=sum/(n-b*m);                      if(i==n)                        {   cout <<average<<endl;                           sum=0;average=0;}                        }}}} 
     代码虽然比较长,但是却能提供一个清晰的思路,个人认为还是值得的。对于不能整除的部分,我们通过求余数的方法先拿出来,计算个数,单独进行求平均值。个人感觉好像没什么坑,只是单纯的思路复杂。 
     T5: 有一头母牛,它每年年初生一头小母牛。每头小母牛从第四个年头开始,每年年初也生一头小母牛。请编程实现在第n年的时候,共有多少头母牛?
     这是第一道让我难堪的题目,当天毫无思路。母牛生小牛,小牛要长4年,这怎么求呢?最后想到了数组。定义数组a[4],我们将母牛放在a[0],刚出生的小牛放在a[3],每过一年,a[3]=a[0],a[2]=a[3],a[1]=a[2],a[0]=a[0]+a[1]。也就是说,这样做的话,只有在a[0]中的牛才会生小牛,从而解决了问题。代码如下:#include<iostream>#include<cstring>using namespace std;int main(){    int a[5]={0},n,sum=0,t=0;    while(cin >>n)    {        if(n==0)break;        a[0]=1;        for(int i=1;i<=n;i++)        {sum=a[0]+a[1]+a[2]+a[3];                a[0]+=a[1];                t=a[0];                a[1]=a[2];                a[2]=a[3];                a[3]=t;        }            cout <<sum<<endl;//cout <<a[0]<<a[1]<<a[2]<<a[3];            sum=0;            memset(a,0,sizeof(a));        }}  
     T6:“回文串”是一个正读和反读都一样的字符串,比如“level”或者“noon”等等就是回文串。请写一个程序判断读入的字符串是否是“回文”。 说实话,这道题我是不太会的,所幸书上有一道相似的题,然后就照着葫芦画瓢。先看看代码:#include<iostream>#include<cstdio>#include<cstring>using namespace std;int main(){    char s[105];    int len,i,j,n;    while(cin >>n)    {        for(int k=0;k<n;k++)        {            cin >>s;            len=strlen(s);            i=0;j=len-1;            while(i<=j&&(s[i]==s[j]))            {                i++;j--;            }            if(i>j)cout <<"yes"<<endl;            else cout <<"no"<<endl;        }    }}
      这里运用了一个函数strlen(),意为“字符串()的长度”,要说注意点儿啥,首尾可以一起判断算是一个吧,这样也可以做到优化时间。 
      T7: 输入一个十进制数N,将它转换成R进制数输出。 
      这个题也是不太会,和上一道题一样,看书写呗。书上用了一个自定义函数,用来转换进制,就当是学习一下函数的使用。代码如下:
      #include<iostream>#include<cstdlib>using namespace std;void TurnData(int n,int a);char ch[6]={'A','B','C','D','E','F'};int main(){    int n,a;    while(cin >>n>>a)    TurnData(n,a);    return 0;}void TurnData(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;}
      书上的原题时输入一个10进制数,分别输出2,8,16进制数,本质时一样的。重点解释一下函数部分,对于a进制,实际上就是逢a进1,因而我们可以用求余来做。求余,取余,原数除以a,如此循环,直至原数等于0。
      注意,在我们输出的时候,我们要注意输出的顺序,记住是逆序输出的。而进制高于10时,就需要ABCDEF的帮助。
      T8:求A^B的最后三位数表示的整数。说明:A^B的含义是“A的B次方”。
      这个题本身不难,A的B次方,一个for语句就解决了。只是当A、B取值较大时,不难想象,这是一个天文数字,会非常的大。我们找不到一个存储类型来储存这个数,这就是关键。因而,此题可以巧妙转换。我们知道,要知道一个幂的后三位,只需要对这个数一直%1000即可,比如1230%1000=230;2323456789%1000=789......这样我们这个问题就简单了,只要每次乘以一个数对1000取余即可。代码如下:
      #include<iostream>using namespace std;int main(){    int m,n,r;    while(cin>>m>>n&&m>0&&n>0)    {        r=1;        m%=1000;        for(int i=1;i<=n;i++)            r=r*m%1000;        cout<<r<<endl;    }}
      T9:有一只经过训练的蜜蜂只能爬向右侧相邻的蜂房,不能反向爬行。请编程计算蜜蜂从蜂房a爬到蜂房b的可能路线。
      这道题就用到了递推的方法,1→2只有1种方法,1→3有2种,1→4有3种,1→5有5种,到这里我们大概可以猜到了,从第三个开始,每一个的数量等于前两个的数量和,从而找到了递推公式:a[n]=a[n-1]+a[n-2],题目就顺利解决了。不过,这里有一个坑,当蜜蜂从1→50时,如果我们用int定义,我们就会发现,结果是负数,也就是说,int 对于这道题不够用了,因而我们选用long long int进行定义。具体代码如下:    #include<iostream>using namespace std;int main(){    long long int a[50]={0};    int m,n,b;    cin >>b;    for(int i=1;i<=b;i++)    {        cin >>m>>n;            a[1]=1;            a[2]=2;            a[3]=3;            a[4]=5;        for(int j=5;j<=n-m;j++)        {            a[j]=a[j-1]+a[j-2];        }        cout <<a[n-m]<<endl;}}
      另外,除了这道题外,上楼梯的解题思路同样是运用递推,因而不再展开介绍,请读者自行思考。
      T10:有如下方程:Ai = (Ai-1 + Ai+1)/2 - Ci (i = 1, 2, 3, .... n).若给出A0, An+1, 和 C1, C2, .....Cn.请编程计算A1 = ?
      这道题猛地一看好像和上一题一个样,都是递推,而且还将递推公式告诉我们了,那这道题不是很easy吗?然后就照着这个公式写,呵呵,wrong answer.其实,这道题并没有我们想象的那么简单,这个递推公式并不是我们所要的,也算得上是一个坑吧,真正的递推公式需要我们自己去推:	n=1时,2a1=a0+a2-c1    n=2时,3a1=2a0+a3-4c1-2c2n=3时,4a1=3a0+a4-6c1-4c2-2c3……n=k时,(k+1)a1=ka0+ak-2kc1-(2k-1)c2-……-2ck这才是真正的公式。我们将这个公式带进去就对了,代码如下:   
       #include <iostream>#include <cstdio>using namespace std;int main(){    int n;    double A0, An,A1,k;    double c[3005];    while(cin >>n)    {        cin >>A0>>An;        for(int i = 1; i <= n; i++)            cin >>c[i];        A1 = n / (n + 1.0) * A0 + 1.0 / (n + 1) * An;         k = n * 2.0;        for(int j = 1; j <= n; j++)        {            A1 -= k / (n + 1) * c[j];            k -= 2.0;        }        printf("%.2lf\n", A1);    }    return 0;}
       T11:参加过上个月月赛的同学一定还记得其中的一个最简单的题目,就是{A}+{B},那个题目求的是两个集合的并集,今天我们这个A-B求的是两个集合的差,就是做集合的减法运算。
       首先我们要先读懂题目,A-B是什么意思。多读几遍会明白的。其实,A集合是主体,我们需要判断对于A集合中的每个元素,是否能在B集合中找到一个相同的数与之对应,如果有,我们在输出时就不用再输出这个数了,这便实现了A-B,而当A集合中所有的元素在B中都有一个与之对应的话,这时便是空集,我们输出“NULL”,结束。代码如下:#include<algorithm>#include<cstdio>using namespace std;int main() {    int a[100],b[100],C[100];    int i,j,k;    int n,m;    while(cin >>n>>m)    {   int d[100]={0},num=0;    if(m==n&&m==0)return 0;    else    {    for(i=0;i<n;i++)cin >>a[i];    for(i=0;i<m;i++)cin >>b[i];    for(j=0;j<n;j++)    {        for(k=0;k<m;k++)        {            if(a[j]==b[k])d[j]= 1; }        }        for(i=0;i<n;i++)        {     if(d[i]!=1)        {      sort(a, a + n);         cout <<a[i]<<" ";        C[num++]=a[i];     }    }        if(num==0)cout <<"NULL";        cout <<endl;   }  } }
       T12:在一个平面内有两个点,求两个点分别和原点的连线的夹角的大小。注:夹角的范围[0,180],两个点不会在圆心出现。
       这算是一道数学题,我们可以利用余弦定理来解题,个人认为唯一要注意的地方就是如何将余弦值转换成角度值。我们先看一下代码:#include<iostream>#include<cmath>#include<cstdio>using namespace std;const double PI=3.1415926;int main(){    int t;    double x1,x2,y1,y2,a,b,c,d,e;    cin >>t;    for(int i=1;i<=t;i++)    {        cin >>x1>>y1>>x2>>y2;        a=sqrt((x1*x1)+(y1*y1));        b=sqrt((x2*x2)+(y2*y2));        c=sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));        d=(a*a+b*b-c*c)/(2*a*b);        e=acos(d);        printf("%.2lf",e*180/PI);        cout <<endl;    }}
       这里我们运用了一个数学函数:acos(),即反三角函数,可以将余弦值转换成弧度,然后我们就好转换成角度了。
       T13:一个整数,只知道前几位,不知道末二位,被另一个整数除尽了,那么该数的末二位该是什么呢?
       这个题并不难,只是有一个坑,如果用一般的方法,我们会发现,如果这个数的后两位都是0的话,结果只会输出“0”而不是两个0。为了避免这个问题,我用分类的方法,既然它少一个0,那我自己加一个不就好了。所以让我们来看一下代码:
      #include<iostream>using namespace std;int main(){    int a,n,b,e;    while(cin >>a>>b)    {        e=1;        if(a==0&&b==0)        break;        for(int i=0;i<=9;i++)        for(int j=0;j<=9;j++)        {            n=100*a+10*i+j;            if(n%b==0)            {                if(i!=0)                {if(e==1)                cout <<10*i+j;                else cout <<' '<<10*i+j;                e++;            }            else             {if(e==1)                cout <<'0'<<j;                else cout <<' '<<'0'<<j;                e++;            }            }}cout <<endl;    }}
      T14:把一个偶数拆成两个不同素数的和,有几种拆法呢?
      这个题我们可以分两步去做:第一步,我们可以先求出比这个偶数小的所有素数。第二步,用循环来判断是否能拆成两个素数,每有一种,数量加一。具体代码如下:#include<iostream>#include<cmath>using namespace std;int c[1000]={0};int main(){    int n,a,b=0,k=1;    while(cin >>n)    {        if(n==0)break;        b=0;k=1;        for(int i=2;i<n;i++)        {            a=0;            for(int j=2;j<=sqrt(i);j++)            {               if(i%j==0)a++;            }        if(a==0){c[k]=i;k++;}        }        for(int i=1;i<k;i++)        {            for(int j=i+1;j<=k;j++)            if(c[i]+c[j]==n)b++;        }        cout <<b<<endl;    }}
      T15:有二个整数,它们加起来等于某个整数,乘起来又等于另一个整数,它们到底是真还是假,也就是这种整数到底存不存在,实在有点吃不准,你能快速回答吗?看来只能通过编程。例如:x + y = 9,x * y = 15 ? 找不到这样的整数x和y。1+4=5,1*4=4,所以,加起来等于5,乘起来等于4的二个整数为1和4,7+(-8)=-1,7*(-8)=-56,所以,加起来等于-1,乘起来等于-56的二个整数为7和-8。
      这道题也算是一道数学题,考察我们对公式法的运用情况。即:x=[-b+(-)sqrt(b*b-4ac)]/2a  代码如下:#include<iostream>#include<cmath>#include<cstdio>using namespace std;int main(){    int n,m;    double a,b;    while(cin >>n>>m)    {        if(n==0&&m==0)break;        a=1.0*(n-sqrt(n*n-4*m))/2;        b=1.0*(n+sqrt(n*n-4*m))/2;        if(a==(int)a&&b==(int)b)cout <<"Yes"<<endl;        else cout <<"No"<<endl;    }}
      我们如何判断结果是不是整数呢?首先,我们将其定义为double,求出结果后将其和用int进行强制转换后的数据进行比较,如果二者相等,那么这个数就是整数。

Summary:
写到这里,说明已经接近了尾声,通过这将近一周的c++编程,自己确实收获了许多,也成长了许多。老实说,有一些题的做法,之前并没有使用过或者说学习过,但是没办法,不会就要抓紧时间将它弄懂,比如:递推、进制转换……我曾怀疑过这些题目的意义,有些都没有学过如何去做,为什么还要我们去做,有什么意义吗?现在我想我明白了,这些题不仅仅只是考察一个人的编程能力,同时还考验一个人的学习能力,在有限的时间内,能否自主学习新知识来解决一系列问题。虽说自己并没有将所有的题目全部完成,算是一点遗憾,不过已经满足了,正如老师所说,做这些题目的意义,并不是为了答题而答题,而是为了学会一门知识。授之以鱼不如授之以渔,就是这个道理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值