程序设计课程论文
一.从原点到达各个蜂房可能得路线数
解题思路:我先找的规律,写了一下要到达的蜂房号与路线数,得到如下规律:
从原点出发要到达的蜂房号:1 2 3 4 5 6
可能的路线数: 1 1 2 3 5 8
已经得出规律,到达第n个蜂房可能的路线数a[n]=a[n-1]+a[n-2];
这符合斐波那契数列:f(n)=f(n-1)+f(n-2),后面的母牛生小牛问题,爬楼梯问题与此类似,但也有不同之处。
源码:
#include<iostream>
using namespace std;
int main()
{
long long int c[60];
int i,a,b,x,n;
c[1]=1;
c[2]=1;
for(i=3;i<=60;i++)
{
c[i]=c[i-1]+c[i-2];
}
cin>>n;
while(n--)
{
cin>>a>>b;
x=b-a;
cout<<c[x+1]<<endl;
}
return 0;
}
细节处理:从原点到达第三个蜂房开始才有规律,前面的列举出来就行;蜜蜂从a蜂房到b蜂房的各种可能路径,相当于从第1蜂房到第b-a+1蜂房,在输出时要注意是输出c[b-a+1]的值
感想:这个题找出规律来就解决了。
二 .求多项式1-1/2+1/3-1/4……前n项的和
解题思路:这是个累加求和的问题,只不过每项的正负不同,可以找出多项式第i项的通项公式,然后累加就可以了。
源码:
#include<iostream>
#include<cstdio>
#include<iomanip>
#include<cmath>
using namespace std;
int main()
{
int m,n,i,j;
cin>>m;
for(j=1;j<=m;j++)
{
while(cin>>n)
{
double x=0;
for(i=1;i<=n;i++)
{
x+=pow(-1,i+1)*(1.0/i);
}
cout<<fixed<<setprecision(2)<<x<<endl;
}
}
return 0;
}
细节处理:在找第i项的通式时会用到pow函数,pow(a,b)表示a的b次方,头文件就是#include<cmath>;注意循环n次;注意最后输出的格式为保留两位小数。
感想:在某些比较麻烦的问题上,运用函数会使问题变得简便。
三.长度为n的数列,每m个数求一个平均值
解题思路:我感觉思路比较清晰,就是一个长度为n的数列,按顺序每m个数输出一个平均值,如果最后一组数据不到m个了,就是剩下的实际数字求平均值。
源码:
#include<iostream>
using namespace std;
int main()
{
int i,n,m;
int b[1100];
while(cin>>m>>n)
{
int x=0,s=0,y=0;
for(i=1;i<=n;i++)
{
if(x==m)
{
x=0;
b[s++]=y/m;
y=0;
}
x++;
y+=i*2;
}
if(y!=0)
{
b[s++]=y/x;
}
for(i=0;i<s;i++)
{
if(i==s-1)
{
cout<<b[i]<<endl;
}
else
{
cout<<b[i]<<" ";
}
}
}
return 0;
}
细节处理:因为我感觉这个细节处理比较繁琐,所以在代码旁边进行备注。
#include<iostream>
using namespace std;
int main()
{
int i,n,m;
int b[1100];
while(cin>>m>>n)
{
int x=0,s=0,y=0;
for(i=1;i<=n;i++)
{
if(x==m) //输入m个数字以后,这一组就算确定了
{
x=0; //然后x归0,再进行下一组m个数的操作
b[s++]=y/m; //求这m个数的平均值
y=0; //y归0
}
x++; //每输入一个数字,x加一
y+=i*2; //数列的前m个数字求和
}
if(y!=0) //如果最后一组数不足m个,就执行这条语句
{
b[s++]=y/x; //实际x个数求平均值
}
for(i=0;i<s;i++)
{
if(i==s-1) //最后一个数的输出,不要空格
{
cout<<b[i]<<endl;
}
else
{
cout<<b[i]<<" "; //前s-1个数输出是要用空格间隔
}
}
}
return 0;
}
感想:我感觉这个题的思路简单,但是细节处理很麻烦,处理很多次都出现错误
四.去掉一个最高分、一个最低分,求平均得分
解题思路:假设一共有n个分数,将这些分数由低到高排序,然后去掉第一个和最后一个,对剩下的n-2 个数字求平均值,这个题思路不难,但是我想写一下冒泡排序,顺便回顾一下排序问题。
源码:
#include<iostream>
#include<cstdio>
#include<iomanip>
using namespace std;
int a[110];
int main()
{
int n,i,j,t;
while(cin>>n)
{
for(i=1;i<=n;i++)
{
cin>>a[i];
}
for(j=1;j<=n-1;j++)
{
for(i=1;i<=n-j;i++)
{
if(a[i]>a[i+1])
{
t=a[i+1];
a[i+1]=a[i];
a[i]=t;
}
}
}
int x=0;
double m=0;
for(i=2;i<=n-1;i++)
{
x+=a[i];
}
m=(1.0*x)/(n-2);
cout<<fixed<<setprecision(2)<<m<<endl;
}
return 0;
}
细节处理:注意冒泡排序;最后只有n-2个数;注意小数点保留位数;在排序时可以使用sort函数,若对n个数排序,格式为sort(a+1,a+n+1)(从a[1]开始的)
感想:平时老师讲的一些方法技巧一定要掌握,在做题时会有惊喜的
五.判断回文串
解题思路:将一串字符一端从头,一端从尾,看首尾的字符是否相同,然后再从两端向中间判断,依次对比相对应的位置字符是否相同;只要有一处对应位置的字符有不同情况,就可以得出此字符串不是回文串。
源码:
#include<iostream>
#include<cstdio>
#include<iomanip>
#include<string>
using namespace std;
int main()
{
int n,i,j;
string s;
cin>>n;
for(i=0;i<n;i++)
{
cin>>s;
int x=0;
for(j=0;j<s.size()/2;j++)
{
if(s[j]!=s[s.size()-1-j])
{
x=1;
break;
}
}
if(x==0)
{
cout<<"yes"<<endl;
}
else
{
cout<<"no"<<endl;
}
}
return 0;
}
细节处理:注意字符串的定义,头文件为#include<string>;string用来处理字符串的类。
六.判断表达式的值是否为素数
解题思路:写出表达式的值,判断表达式的值是否为素数
源码:
#include<iostream>
#include<cstdio>
#include<iomanip>
using namespace std;
int a[100];
int main()
{
int x,y,n,j,s;
int i;
while(cin>>x>>y)
{
if(x==0&&y==0)
break;
i=0;
for(n=x;n<=y;n++)
{
a[i]=n*n+n+41;
i++;
}
int m=0;
s=y-x;
for(i=0;i<=s;i++)
{
for(j=2;j<a[i];j++)
{
if(a[i]%j==0)
{
m++;
break;
}
}
}
if(m==0)
{
cout<<"OK"<<endl;
}
else
{
cout<<"Sorry"<<endl;
}
}
return 0;
}
细节处理:当x、y的值均为0时,该行不做处理;只有每个值都为素数的时候,才可以输出yes,只要在x、y的取值范围内有一个值不是素数,就不符合要求了。
感想:判断是否为素数最直观和简单的方法就是从2开始直接除,一直除到自身的值减一,能除尽(余数为0)就不是质数;还有一种判断方法,判断一个数是否是质数,只需判断它是否能被小于它开跟号后的所有数整除,都能整除,则为素数。
七.求集合A与集合B的差集
解题思路:将集合A与集合B中的元素分别存在两个数组里,然后我们要找的元素在集合A里面,不在集合B里面,这两个条件要同时成立,挑出来的元素才符合要求。
源码:
#include<iostream>
#include<algorithm>
using namespace std;
int a[110],b[110];
int main()
{
int n,m,i,j,k;
while(cin>>n>>m)
{
if(m==0&&n==0)
{
break;
}
k=0;
for(i=1;i<=n;i++)
{
cin>>a[i];
}
for(j=1;j<=m;j++)
{
cin>>b[j];
}
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
if(a[i]==b[j])
a[i]=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;
}
细节处理:因为要求从小到大输出结果,所以运用sort函数进行排序;输出时的格式问题一定要注意;如果有好几个循环或者有嵌套,一定要搞清楚它们之间的关系,不能混沌。
八.判断两个数是否为亲和数
解题思路:a的真约数之和为b,如果b的真约数之和也等于a,那么称a与b为亲合数;要这从两个方面判断,求出a的真约数,累加求和,如果求和与b的值相同,再去判断b的真约数之和是否等于a;如果a的真约数之和不等于b,那就不用判断了,a与b一定不是亲和数了。
源码:
#include<iostream>
#include<cstdio>
#include<iomanip>
using namespace std;
int main()
{
int m;
cin>>m;
while(m--)
{
int i,a,b,x=0,y=0;
cin>>a>>b;
for(i=1;i<=a-1;i++)
{
if(a%i==0)
x=x+i;
}
if(x==b)
{
for(i=1;i<=b-1;i++)
{
if(b%i==0)
y=y+i;
}
if(y=a)
{
cout<<"YES"<<endl;
}
else
{
cout<<"NO"<<endl;
}
}
else
{
cout<<"NO"<<endl;
}
}
return 0;
}
细节处理:中间关键部分是在一个条件成立的情况下判断另一个条件是否成立,要理清思路;两个条件是"且"的关系。当然,第一个条件不成立,结论自然不会成立了。
感想:注意理清各个条件之间的关系
九.给老师发工资,至少准备多少张人民币
解题思路:将每个老师的工资存到一个数组中,然后算出每一位老师的工资所需要的人民币数,最后将每一位老师所需要的工资的人民币数加起来,就是至少需要准备的人民币数了。
源码:
#include<iostream>
#include<cstdio>
#include<iomanip>
using namespace std;
int a[110];
int main()
{
int n,i,x,b,c,d,e,f,m;
while(cin>>n)
{
if(n==0)
{
break;
}
else
{
x=0;
for(i=1;i<=n;i++)
{
cin>>a[i];
}
for(i=1;i<=n;i++)
{
b=a[i]/100;
c=(a[i]%100)/50;
d=(a[i]%100)%50/10;
e=(a[i]%100)%50%10/5;
f=(a[i]%100)%50%10%5/2;
m=(a[i]%100)%50%10%5%2;
x+=b+c+d+e+f+m;
}
cout<<x<<endl;
}
}
return 0;
}
细节处理:每位老师的工资要先计算需要100元的人民币多少张,其次分别是50元、10元、5元、2元、1元的,要注意这个顺序;在计算不同面值的人民币所需要的张数时要特别小心;最后累加求和就行了。
感想:在计算每位老师所需要的不同面值的人民币张数的时候需要特别小心,容易出错。
十.推公式求a1
解题思路:我感觉这是一个找规律的题,先找一下规律
a1=(a0+a2)/2-c1;
a2=(a1+a3)/2-c2;
得出:a1+a2=a0+a3-2(c1+c2);
同理可得:
a1+a1=a0+a2-2c1;
a1+a2=a0+a3-2(c1+c2);
a1+a3=a0+a4-2(c1+c2+c3);
a1+a4=a0+a5-2(c1+c2+c3+c4);
……
a1+an=a0+an+1-2(c1+c2+c3+……+cn)
等式两边想加,得到a1的表达式
a1=[n*a0+an+1-2*(cn+2cn-1+3cn-2+……ncn)]
得出a1的表达式来后就好办了,这个题基本就解决了。
源码:
#include<iostream>
#include<string>
#include<algorithm>
#include<iomanip>
using namespace std;
int main()
{
double a[3100];
double c[3100];
int n;
while(cin>>n)
{
cin>>a[0]>>a[n+1];
for(int i=0;i<n;i++)
{
cin>>c[i];
}
double a1=a[0]*n+a[n+1];
for(int i=1;i<=n;i++)
{
a1-=2.0*i*c[n-i];
}
cout<<fixed<<setprecision(2)<<a1/(n+1)<<endl;
}
return 0;
}
细节处理:可以把an和cn的值放到两个数组中;定义变量是定义为double;注意最后输出时要保留两位小数。
感想:这种题就是找规律,找到规律题就解决了,不要怕麻烦,在本子上推一推公式,规律就找出来了。
十一.算买菜花的钱
解题思路:算一共买菜花了多少钱,每一种蔬菜的单价*数量求出每一种蔬菜花的钱,再把每种蔬菜花的钱加起来,就是买菜一共花的钱了。
源码:
#include<iostream>
#include<string>
#include<iomanip>
using namespace std;
int main()
{
string a;
double b,c,sum=0;
while(cin>>a>>b>>c)
{
sum+=b*c;
}
cout<<fixed<<setprecision(1)<<sum<<endl;
return 0;
}
细节处理:蔬菜的名称定义为字符串,string型,蔬菜的数量和单价定义为double型;注意保留一位小数;求和的变量要赋初值。
十二.求a的b次方最后三位数表示的整数
解题思路:乘积的最后三位的值只与乘数和被乘数的后三位有关,与乘数和被乘数的高位无关,所以我们一共算b次,算一次取余一次,就当是只进行一个数的最后三位数的计算。
源码:
#include<iostream>
#include<cstdio>
#include<iomanip>
#include<cmath>
using namespace std;
int main()
{
int A,B,x,i;
while(cin>>A>>B)
{
if(A==0&&B==0)
{
break;
}
x=1;
for(i=1;i<=B;i++)
{
x=(A*x)%1000;
}
cout<<x<<endl;
}
return 0;
}
细节处理:每进行一次计算就取余一次;考虑到a的b次方数可能比较大,所以不用pow(a,b)来进行;注意当a=0并且b=0时要特判。
感想:如果运行的数比较大时,要考虑超时问题,并且优化代码,解决超时问题。
十三.求两个时间相加后得到的时间
解题思路:先从秒开始加,然后再加分钟,两者都满足满60进1的原则,最终加小时数
源码:
#include<iostream>
#include<cstdio>
#include<iomanip>
using namespace std;
int main()
{
int i,m,n,j;
int a[100],b[100],s[100];
cin>>n;
while(n--)
{
for(i=1;i<=3;i++)
{
cin>>a[i];
}
for(j=1;j<=3;j++)
{
cin>>b[j];
}
int x=0;
for(j=3;j>=1;j--)
{
s[j]=a[j]+b[j]+x;
if(j!=1&&s[j]>=60)
{
x=s[j]/60;
s[j]=s[j]%60;
}
else
{
x=0;
}
}
for(i=1;i<=3;i++)
{
if(i==3)
{
cout<<s[i]<<endl;
}
else
{
cout<<s[i]<<" ";
}
}
}
return 0;
}
细节处理:秒与秒相加,不要忘了进位(满60进1);分与分相加,不要忘了加上进位,同时不要忘了进位(满60进1);时与时相加,不要忘了加上进位;一定要先加秒数,再算分数,最后算小时数;输出时格式一定要特别注意,输完小时数后加上空格再输分数,输上空格再输秒数,输完秒数后不要输空格,要换行。
十四.在有序数列中插入一个数,使之仍然有序
解题思路:将数列中的数存放到一个数组中,将要插入的数也存到该数组中,然后将新数组重新排序,这样得到的新数列仍然有序。
源码:
#include<iostream>
#include<cstdio>
#include<iomanip>
#include<algorithm>
using namespace std;
int a[110];
int main()
{
int n,i,m;
while(cin>>n>>m)
{
if(n==0&&m==0)
{
break;
}
for(i=1;i<=n;i++)
{
cin>>a[i];
}
a[n+1]=m;
sort(a+1,a+n+2);
for(i=1;i<=n+1;i++)
{
if(i==n+1)
{
cout<<a[n+1]<<endl;
}
else
{
cout<<a[i]<<" ";
}
}
}
return 0;
}
细节处理:m=0并且n=0时要特判;使用sort函数进行排序;输出前n个数时,每输出一个数字都要输出一个空格,输出最后一个数字时,不要再输出空格。
十五.将n个整数按绝对值从大到小排序
解题思路:利用冒泡排序,比较相邻两个数的绝对值,不断比较,交换,n个元素比较n-1轮,第i轮比较n-i次。
源码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<string>
using namespace std;
int a[100];
int main()
{
int n,i,j;
while(cin>>n)
{
if(n==0)
{
break;
}
for(i=0;i<n;i++)
{
cin>>a[i];
}
for(i=0;i<n;i++)
{
for(j=i+1;j<n;j++)
{
if(abs(a[j])>abs(a[i]))
{
swap(a[i],a[j]);
}
}
}
for(i=0;i<n;i++)
{
if(i==n-1)
{
cout<<a[i]<<endl;
}
else
{
cout<<a[i]<<" ";
}
}
}
return 0;
}
细节处理:n=0时要特判;while(cin>>n)表示输入一个n,循环进行一次;冒泡排序的运用;输出前n-1个数时要有空格间隔,输出第n个数时不要有空格。
总结: 写完这些代码,感觉自己有一点点懂得如何写代码了。我们上课学的理论概念,要在写代码的过程中一点点地去熟悉,去运用。当然对于一些基本的方法,如如何排序(冒泡排序、选择排序、插入排序、使用sort函数)、怎样求素数,有一些题可暴力枚举等等一些东西,心里也要有。写代码也是一个细心的活,计算机对你很严格,不容你去违背它的想法,你有一点点不按它的意思来,它就不让你通过。想要学好程序设计,就要多练,多想,多总结。只有一个学期的时间,学习的东西太少太少,以后希望自己能够多学习一些有关程序设计的内容,不能止步于此。