C语言总复习

                  problem 1

简要题意
爬楼梯,每次跨一级或两级,要走上M级,共多少种走法? 输入一个整数n,表示测试个数,然后是n行数据,每行包含一个整数M,表示楼梯阶数 输出每组测试数据的不同走法的数量
解题思路 爬楼梯的爬法数目符合斐波那契数列,可以这样想:设S(n)表示走n级台阶的走法数量。走n级台阶,第一步只有两种选择:可以选择走1阶,然后还有S(n-1)种走法;选择走2阶,那么接下来有S(n-2)种走法。那么S(n) = S(n-1) + S(n-2)。
解题细节 注意刚开始时我准备用比较普通的方法解题,但每次都超时,这题的关键就是找到规律。源码: #include
using namespace std;
int num;
long long DP[51];
long long dp(int n)
{
DP[0]=0;
DP[1]=1;
DP[2]=2;
for(int i=3;i<=n;i++)
{
DP[i] = DP[i-1]+DP[i-2];
}
return DP[n];
}
int main()
{ cin>>num;
cout<<dp(num)<<endl;
return 0;}
总结一下,这道题其实真正实现起来不难,每个人都能用C++编写出斐波那契数列从而得到正确的值,但是问题在于能否发现这是一道斐波那契数列题。 problem 2
简要题意
有如下方程:Ai = (Ai-1 + Ai+1)/2 - Ci (i = 1, 2, 3, … n).若给出A0, An+1, 和 C1, C2, …Cn.请编程计算A1 = ?
解题思路:
这是一道数学规律题,通过多算几组数据找到其中的规律 可由已经给出的函数,推导出 n=3;4A1=3A0+A4-6C1-4C2-2C3 n=2;3A1=2A0+A3-4C1-2C2 n=1;2A1=A0+A2-2C1故当n=k时,(k+1)A1=kA0-2(kC1+(k-1)C2+…+Ck)然后得到A1的表达式
解题细节:
注意结尾需要保留两位小数,相对于用cout输出,printf在这时显得更简单源码:
#include
#define N 3000+10
double c[N], d[N];
using namespace std;
int main()
{ int n;
double af, al, A=0.0;
while(cin>>n)
{
double a=0.0;
cin>>af>>al;
a=n
af+al;
for(int i=1,j=n;i<=n;i++,j–)
{ cin>>c[i];
d[i]=2
c[i];
a-=jd[i];
}
A=a/(n+1);
printf("%.2lf\n",A); }
return 0;}
总结:这道题在刚开始做时,真是一点思路都没有,但当真做完后,就觉着这道题其实也没啥,关键就是找到其中隐藏的规律,因此在做题时要有足够的耐心,认真读好题,才不至于一遍又一遍地错。
problem 3
简要题意 对于表达式n^2+n+41,当n在(x,y)范围内取整数值时(包括x,y)(-39<=x<y<=50),判定该表达式的值是否都为素数。输入数据有多组,每组占一行,由两个整数x,y组成,当x=0,y=0时,表示输入结束,该行不做处理
解题思路 这个题完全可以用老师上课讲的判定素数的函数,用此方法解题很简单,但我也因为不经常使用函数,在提交时错了很多遍。
解题细节 在解题时千万不要漏掉表达式等于1时的特殊情况,我就是因为漏掉了它,总是通不过。
源码:
#include
#include
using namespace std;
int prime(int x)
{ int i,n;
n=sqrt(x);
for(i=2;i<=n;i++)
{ if(x%i0) return 0; }
return 1;}
int main(){
int x,y,i,j,p,a[100];
while(cin>>x>>y)
{ p=0,j=0;
if(x
0&&y==0) break;
for(i=x;i<=y;i++)
{ j++;
a[j]=i
i+i+41;
}
for(j=1;j<=y-x+1;j++)
{
if(prime(a[j])&&a[j]!=1) p++;
}
if(py-x+1) cout<<“OK”<<endl;
else cout<<“Sorry”<<endl;}}
总结:在编写程序时,用一些自定义的函数可以使自己的代码看起来更整洁,并且更好理解,同时,在写代码时,各种条件一定要考虑周全。
problem 4
简要题意: 水仙花数是指一个 n 位数(n≥3 ),它的每个位上的数字的 n 次幂之和等于它本身(例如:1^3 + 5^3+ 3^3 = 153,现求n到m区间内所有水仙花数
解题思路: 通过循环,将区间n到m内的水仙花数全部存入数组内,待循环完毕后,判断数组内的数,若为0,则输出no,否则输出yes
解题细节: 在输入n,m时,先输入n,后输入m.输出水仙花数时要求从小到大,且有空格
源码:
#include
using namespace std;
int main(){
int x[1010];
int i,j=0,k=0,n,m,a=0,d=0;
while(cin>>n>>m)
{ d=0;
for(i=n;i<=m;i++)
{ a=i/100;
j=(i%100)/10;
k=i%10;
if(a100+j10+k
aaa+jjj+kkk)
{ x[d++]=i;
} }
if(d0) cout<<“no”<<endl;
else {
for(i=0;i<d;i++) {
if(i!=d-1) cout<<x[i]<<" ";
else cout<<x[i]<<endl; } } }return 0;}
总结:在写代码时注意审题,刚开始交时,我就是因为n与m输反了,导致了wa,因此在以后写代码时,一定注意审题。
problem 5
简要题意: 求出a到b之间不含有连续的62 不含有4的数的个数
解题思路: 先将从1到100000之间所有的含有连续62和4的数全部记录,即进行预处理,将数据存入数组中,然后输入n,m便可以直接从中找到不合理的数,最后用所有的牌号减去不合理的牌号即为所求。
解题细节: 在最后输出时区间n,m间车牌个数是m-n+1个。
源码:
#include
#define M 1000000+10
using namespace std;
int a[M];int main()
{ int n, m, c=0;
for(int i=1;i<=1000000;i++)
{ int z=i, q;
while(z)
{ q=z%10;
z=z/10;
if(q
4)
{ c++;
break; }
else if((q2)&&(z%106))
{ c++;
break; } }
a[i]=c; }
while(cin>>n>>m) {
if(n0&&m0) break;
else
cout<<m-n+1-(a[m]-a[n-1])<<endl; }
return 0;}
problem 6
简要题意:有n(n<=100)个整数,已经按照从小到大顺序排列好,现在另外给一个整数x,请将该数插入到序列中,并使新的序列仍然有序。
解题思路:将原来的数组输进后,开始用m进行比较,若m大于a[n-1]则a[n]=m,否则再将m与a[n-2]进行比较,依次比较后便将m插入数组,最后输出新的数组
解题细节: 在插入m后要注意将m后的数依次移位
源码:
#include
using namespace std;
int main()
{ int i,n,m,s[1007];
while(cin>>n>>m)
{ if(m0&&n0) break;
for(i=0;i<n;i++)
cin>>s[i];
if(m>s[n-1])
s[n]=m;
else
{ i–;
while(s[i]>m)
{
s[i+1]=s[i];
i–; }
s[i+1]=m; }
for(i=0;i<=n;i++){
printf("%d",s[i]);
if(i<n) printf(" “);
else printf(”\n"); } }
return 0;}
problem 7
简要题意: 多项式的描述如下: 1 - 1/2 + 1/3 - 1/4 + 1/5 - 1/6 + … 现在请你求出该多项式的前n项的和。输入数据由2行组成,首先是一个正整数m(m<100),表示测试实例的个数,第二行包含m个正整数,对于每一个整数(不妨设为n,n<1000),求该多项式的前n项的和对于每个测试实例n,要求输出多项式前n项的和。每个测试实例的输出占一行,结果保留2位小数
解题思路: 首先观察到多项式奇数项偶数项的符号不同,因此需要进行分类,偶数项前面加负号,剩下的就交给循环进行
解题细节: 测试数据结果保留两位小数,因此在定义时可用double,我在最开始时没有注意以至于输出的结果全是1
源码
#include
using namespace std;
int main()
{ int i,a,n;
cin>>a;
while(a!=0)
{ a–;
cin>>n;
double m=0,p=0;
double sum;
for(i=1;i<=n;i++)
{
if(i%2!=0) m=m+(1.00/i);
if(i%2==0) p=p+((-1.00)/i); }
sum=m+p;
printf("%.2f\n",sum); }}
总结:在出现除法时,要注意带余除法对结果是否有影响。
problem 8
简要题意:求A^B的最后三位数表示的整数
解题思路: 既然是求最后三位数表示的整数,就对该数进行求余,且是三位数的求余,由于题中给的数范围较大,不可能把他求出来,因此这种方法较为简单
解题细节:不能将A直接算出,因为有些A^B的范围超过了64位整型数
源码:
#include
using namespace std;
int main()
{ int i,a,b,c;
while(cin>>a>>b&&(a!=0||b!=0))
{ a%=1000;
c=1;
for(i=1;i<=b;i++)
{ c=c*a%1000; }
cout<<c<<endl; }}
problem 9
简要题意:设有一头小母牛,从出生第四年起每年生一头小母牛,按此规律,第N年时有几头母牛,本题有多组数据。每组数据只有一个整数N,独占一行。(1≤N≤50)。当N为0时,输入结束。
解题思路: 我们只分析n>=4的情况,因为前三年只有1。我们可以设f(i)为第i年母牛的数量,那么f(i)怎么算,我们知道第i年牛的数量肯定等于上一年牛的数量加上第i年新生的牛。因为牛到第四年就可以生小牛,所以到第i年可以生小牛的牛的数量为f(i-3)。所以f(i)=f(i-1)+f(i-3),递推公式出来了,代码很简单。
解题细节: 类似与斐波那契数列,长度由3变为4,则f(n) = f(n-1) + f(n-3)
源码:
#include
using namespace std;
int main()
{ int f[50],i,n;
while(cin>>n&&n!=0)
{ f[1]=1;f[2]=2;f[3]=3;
for(i=4; i<=n;i++)
{ f[i]=f[i-3]+f[i-1]; }
cout<<f[n]<<endl; }
return 0;}
总结;在此次作业中有很多这种找规律类型的题,用到裴波那切数列的题目不在少数,在分析题目时,注意找规律时多向这方面靠拢。
problem 10
简要题意: 在平面内有两个点,求两个点分别和原点的连线的夹脚的大小,输出夹脚大小精确到小数点后两位
解题思路: 使用数学公式向量表达式求出cos x 最后输出时使用反三角函数输出
解题细节: 在正常运算时,其中的圆括号个数很多,注意区分。使用的反三角函数与实际的不同,应为acos x

源码:
#include
#include
#define PI
acos(-1)int main()
{ int u; double x1,x2,y1,y2;
double ans;
scanf ("%d",&u); while (u–)
{ scanf ("%lf %lf %lf %lf",&x1,&y1,&x2,&y2);
ans = (x1 * x2 + y1 * y2) / (sqrt(x1x1+y1y1) *
sqrt(x2x2 + y2y2));
ans = acos(ans) * 180 / PI;
printf ("%.2lf\n",ans); }
return 0;}
总结:这是第一次见到使用反三角函数的代码,一定要记住哦!
problem 11
简要题意:一个整数,只知道前几位,不知道末二位,被另一个整数除尽了,那么该数的末二位该是什么。
解题思路: 第一个数乘一百,然后进行循环,每次加一,当循环到某次,对第二个数求余为零时,输出循环次数,即尾数。
解题细节: 注意输出时控制空格,还有,十位上为0的要补0。
源码:
#include<stdio.h>
int main( )
{ int a,b,i,flag;
while(scanf("%d%d",&a,&b),a&&b)
{ flag=0; for(i=0;i<100;i++)
{ if((a100+i)%b0)
{ if(flag
0)
{ flag=1;
printf("%02d",i); }
else
printf("% 02d",i); } }
printf("\n"); }
return 0;}
problem 12
简要题意:把一个偶数拆成两个不同素数的和,算有几种拆法
解题思路: 在开头写一个判断素数的函数备用,在主函数内对输入的n进行拆分,分为i,n-i,然后用判断素数的函数进行判断,最后输出个数。
解题细节: 注意1既不是素数也不是合数,在开始写时,我姐因为没注意这一点错了好长时间
源码:
#include
#include
using namespace std;
bool pri(int k)
{ int i;
for(i=2;i<=sqrt(k);i++)
if(k%i0) break;
if(i>sqrt(k)) return 1;
return 0;}
int main()
{ int n;
while(cin>>n,n)
{ int count=0;
for(int k=2;k<n/2;k++)
if(pri(k)&&pri(n-k))
count++;
cout<<count<<endl; }
return 0;}
problem 13
简要题意: 判断一个数十进制数字相加是否等于十六进制和十二进制数字相加,若是输出n is a Sky Number. 否则输出 n is not a Sky Number.
解题思路: 先自定义一个函数 用来计算转换后每一位的数,在主函数内便只需判断三种转换后数字加起来是否相等即可
解题细节: 在输出 is a Sky Number.时,不要忘了最后的句号
源码:
#include <stdio.h>
#include <stdlib.h>
int g(int m,int n)
{ int sum=0;
while(m)
{ sum+=m%n;
m=m/n; }
return sum;}
int main()
{ int n,a,b,c;
while(~scanf("%d",&n)&&n)
{ a=g(n,10);
b=g(n,12);
c=g(n,16);
if(a
b&&b==c)
printf("%d is a Sky Number.\n",n);
else printf("%d is not a Sky Number.\n",n); }
return 0;}
problem 14
简要题意: 有二个整数,它们加起来等于某个整数,乘起来又等于另一个整数,它们到底是真还是假
解题思路: 由x+y=n,x
y=m可推知x,y为某方程的根,我们可以通过根与系数的关系来做这道题,又因为根是整数,这需要sqrt()是整数,由此得到以下代码
解题细节: 在输出时注意Yes No均为首字母大写
源码:
# include
# include
using namespace std;
int main()
{ int n,m;
int t;
while(cin>>n>>m,n!=0||m!=0)
{ int num = nn - 4m;
t = sqrt(num);
if(tt==num)
{ cout<<“Yes”<<endl; }
else
{ cout<<“No”<<endl; } }
return 0;}
problem 15
简要题意: 把一个字符三角形掏空,每行包含一个字符和一个整数n(0<N<41),不同的字符表示不同的花纹,整数N表示等腰三角形的高。显然其底边长为2N-1。如果遇到@字符,则表示所做出来的样板三角形已经够了。 每个样板三角形之间应空上一行,三角形的中间为空。显然行末没有多余的空格。
解题思路: 找规律题!首先要考虑到前n-1排和第n排不一样,第n排全部输出(总共2
n-1个字符),而前n-1排需要找规律:第一个字符所在的位置为n-(i-1),(其中i代表的是第i行);而第二个字符所在的位置是n+(i-1);(注意:最后一个字符后面没有空格!),除下这两个位置在小于等于n+(i-1)的位置上全是空格!
解题细节: 在输出第二个三角形时,注意它与上边的数空了一行。
源码:
#include
#include
using namespace std;
int main()
{ char c;
int n;
int flag=0;
while(cin>>c)
{ if(c==’@’) break;
cin>>n;
if(flag) cout<<endl;
flag=1;
if(n==1) cout<<c<<endl;
else {
cout<<string(n-1,’ ‘)<<c<<endl;
for(int i=1;i<n-1;i++) {
cout<<string(n-i-1,’ ')<<c;
cout<<string(2i-1,’ ')<<c<<endl; }
for(int i=0;i<2
n-1;i++) cout<<c;
cout<<endl;
}getchar();
}return 0;}
总结:在做这道题时,没有注意到在输出第二个三角形时需要空行,因为这个原因,交了好多遍,只能说,认真审题啊!
总结:经过对c语言一个学期的学习,从最初的最基本的顺序循环到后来越来越复杂的数组训练。编程让我看到了一个丰富多彩的信息世界。从最初的hello world,到后来解决越来越多的实际问题,这让我切实感到信息技术对我们实际生活的影响。虽然我们只接触了一个学期的C语言,但通过这段时间的学习,我从最初的抵触,到后来慢慢接受,程序带给我的不仅仅是解决问题的方法,更是在解决过程中逐步探索问题时候的感觉。
刚开始学的时候总感觉力不从心,到后来程序写多了也就适应了。C语言不是想象中那么枯燥无味,相反它是一门多彩的有趣的学科,对一道题目你可以有多种解法,在寻找方法过程中,各种思想,各种做法相互碰撞,最终寻到最合适的那一个,但写出程序并不意味着你的程序就是对的,这还需要你坚持不懈地去调试程序,可能一个小小的错误会让你调试一两个小时,这使得你便需要有足够的耐心去实验,去变通你的代码。

猜你喜欢

转载自blog.csdn.net/weixin_43242117/article/details/85763112