第二次机考复习&第一篇博客,具体内容如下。
“魔鬼在细节。”
目录
-
输入数量无范围限制
5-1
【输入格式】为若干整数,以-1结束(测试数据保证这组数中只有最后一个-1
int i,n;
for(i=1;n!=-1;i++)
{
scanf("%d\n",&n);
}
-
求素数
5-3
请写一段程序计算两个数之间的素数。
【输入格式】
为两个正整数a和b(1<a,b<1000)。
【输出格式】
当a小于b时,计算开区间(a,b)中的所有素数,并按升序输出,当a>=b时,或该区间没有素数则输出error。
注意:输出的素数之间用一个空格分隔,最后一个素数后面没有空格。
#include <stdio.h>
#include <stdlib.h>
int main()
{
int a,b,i,j,m=0; //a,b是区间两端的数,i,j是循环变量,m是累计的素数个数
scanf("%d %d\n",&a,&b);
if(a>=b)
printf("error"); //确认a,b的大小关系
else
{
for(i=a+1;i<b;i++)
{
for(j=2;j<=i;j++)
{
if(i==j)
{
m++;
if(m==1)
printf("%d",i);
else
printf(" %d",i); //注意对空格的分类处理
}
if(i%j==0)
break; //实质:寻找i在2到i-1之间的所有非1与自身的因数
//这句if不能放在if(i==j)语句前,因为到i==j时实质已可以确定i为素数
}
}
if(m==0)
printf("error");
}
return 0;
}
【求素数的优化方案】
eg.求1到n之间的素数
- 2~n-1 n% !=0
- 2~n/2
- 2~√n
n=a*b; a<=b; a<=sqrt(n); b>=sqrt(n);
-
逆序输出
5-5
写一段程序将一个正整数逆序输出。
【输入格式】
为一个正整数,该正整数小于2的31次方。
【输出格式】
将该数的各位数字逆序输出(输入的数字末尾为0时也输出)。
#include <stdio.h>
#include <stdlib.h>
int main()
{
long int n;
scanf("%ld\n",&n);
while(n>0)
{
printf("%ld",n%10); //巧用除余求倒序问题
n = n / 10; //下次循环
}
//也可写成:
//for(;n>0;n/10)
//{
// printf("%ld",n%10);
//}
printf("\n");
return 0;
}
-
回文数
6-4
回文是指正读和反读都一样的数或文本段。例如,12321、55555、45554、11611都是回文数。输入一个长度不超过10位的整数n,判断它是否是回文数。
【输入格式】
只有一个整数n,即待判断的数字。测试用例保证n可以用int存储。
【输出格式】
当n为回文数时输出“Yes”,否则输出“No”。
#include <stdio.h>
#include <stdlib.h>
int main()
{
int n,c=1,t1,t2,w=1,i,j,pd=1; //c是,t1是左侧高位数,t2是右侧低位数,w是位数,pd用于判断
scanf("%d",&n);
j=n/10;
t1=n;
t2=n;
if(j==0)
{
printf("Yes\n");
return 0; //个位数的情况
}
while(j!=0)
{
n/=10;
j=n/10;
c*=10;
w++;
}
for(i=1;i<=w/2;i++)
{
if((t1/c)%10==t2%10)
{
c/=10;
t2/=10;
}
else
{
pd=0;printf("No\n");break;
}
}
if(pd==1)printf("Yes\n");
return 0;
}
-
循环的归零处理
6-2
请写程序计算数列中所有除以3余1且除以5余2的数的和。
【输入格式】
第一行为一个整数n(0<n),代表n组测试用例。后边是n行,每行代表一组测试用例。每行中包含若干整数,以-1结束。测试用例保证每行只有最后一个数为-1,其他数均为正整数。
【输出格式】
为n行,每行一个整数,对应n组测试用例,为求和的结果。测试用例保证合法且所有整数可以用int存储。
#include <stdio.h>
#include <stdlib.h>
int main()
{
int n,m,i,sum;
sum=0;
scanf("%d\n",&n);
for(i=1;i<=n;i++)
{
for(;;)
{
scanf("%d\n",&m);
if(m==-1)
break;
else if(m%3==1&&m%5==2)
sum=sum+m;
}
printf("%d\n",sum);
sum=0; //注意归零
}
return 0;
}
-
打印图形
6-3
用’-‘(减号)、’+’(加号)、’|’(竖线)、’*’星号和空格打印方格。
【输入格式】
只有一行,为用空格分隔的两个整数l,c(0<l,c<10)。其中l和c分别代表格子的行数和列数。请看输入样例。
【输出格式】
每组测试用例输出一组(请看输出样例)。
【输入样例】
在这里给出一组输入。例如:
2 3
【输出样例】
在这里给出相应的输出。例如:
|*****|*****|*****| | | | | | | | |--+--|--+--|--+--| | | | | | | | |*****|*****|*****| | | | | | | | |--+--|--+--|--+--| | | | | | | | |*****|*****|*****|
#include <stdio.h>
#include <stdlib.h>
int main()
{
int l,c,i,j;
scanf("%d %d\n",&l,&c);
for(j=1;j<=l;j++)
{
for(i=1;i<=c;i++)
{
printf("|*****");
}
printf("|\n"); //不怕麻烦,一行行输
for(i=1;i<=c;i++)
{
printf("| | ");
}
printf("|\n");
for(i=1;i<=c;i++)
{
printf("|--+--");
}
printf("|\n");
for(i=1;i<=c;i++)
{
printf("| | ");
}
printf("|\n");
}
for(i=1;i<=c;i++)
{
printf("|*****");
}
printf("|\n");
return 0;
}
-
二维数组求最小值的最大值
7-4
在一个nXn的二维整数数组中,每一行都有一个最小值,这n个最小值中有一个最大的。请写一段程序找出这个最大的最小值。
【输入格式】
第一行为一个整数n,1<=n<=10,后边为n行,是nXn个整数(以空格分隔),即nXn的二维整数数组。
【输出格式】
只有一行为三个整数,依次为这个最大的最小值及它所在行和列的下标(分别以一个空格分隔。如果某行的最小值出现多次,则要求记录列下标最小的那个,如果最大的最小值出现多次,则要求记录下标最小的那行)。测试数据保证所有整数均可以用int型存储。
#include <stdio.h>
int main()
{
int a[11][11]={0},n,i,j,min,max,b[11]={0},f,k; //不能设成a[n],设个大于n的值,再在循环内限制n是一样的
scanf("%d",&n);
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
scanf("%d",&f);
a[i][j]=f;
}
} //完成输入
for(i=0;i<n;i++)
{
min=a[i][0];
for(j=0;j<n;j++)
{
if(a[i][j]<min)
min=a[i][j];
}
b[i]=min;
} //找每行最小值
max=b[0]; //用b[i]来存储最小值(if语句是条件语句,无法达到赋值效果)
for(i=0;i<n;i++)
{
if(b[i]>max)
{
max=b[i];
k=i; //找最小值的最大值,此i非彼i
}
}
for(i=0;i<n;i++)
{
if(a[k][i]==max)
{
break; //找极值点对应的纵坐标
}
}
printf("%d %d %d",max,k,i);
return 0;
}
-
打印螺旋方阵
按要求输出方阵。
【输入格式】
为一个正整数n,0<n<10,代表方阵的阶数。
【输出格式】
从左上角元素开始,用1到n平方的正整数,按顺时针螺旋方式填充nXn二维数组,见样例(当n=4时)。按行输出所得二维数组。每个整数占两个字符位置右对齐,两个整数之间用一个空格分隔。行末没有空格。
【输入样例】
4
【输出样例】
1 2 3 4 12 13 14 5 11 16 15 6 10 9 8 7
一道值得反复琢磨的经典“螺旋打印”题!再次感叹“化繁为简”的魅力!
首先是找到规律,很显然本题要依托无数个循环结构的嵌套。但怎么循环,怎么嵌套呢? 观察样例,不难发现每一个大循环由四个部分组成:上(从左到右)、右(从上到下)、下(从右到左)、左(从下到上)。但是,这四个部分也是在不断变化的,并且每一次变化都有规律可循。由此思考:是否可以将这四个部分用四个小循环表达呢?
从这一角度出发,将四个方向设成四个变量,观察变量循环变化的规律,难题迎刃而解:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int n;
scanf("%d\n",&n);
int left=0,right=n-1,up=0,down=n-1;
int i,j,number=1,s=n*n;
int a[11][11];
while(number<=s)
{
for(i=left;i<=right;i++)
{
a[up][i]=number;
number++;
}
up++;
for(j=up;j<=down;j++)
{
a[j][right]=number;
number++;
}
right--;
for(i=right;i>=left;i--)
{
a[down][i]=number;
number++;
}
down--;
for(j=down;j>=up;j--)
{
a[j][left]=number;
number++;
}
left++;
}
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
if(j!=0)
printf(" %2d",a[i][j]);
else
printf("%2d",a[i][j]);
}
if(i<n-1)
printf("\n");
}
return 0;
}
值得一提的是,第一次做这题时我在网上找到了类似题的代码,但按上文的思路写码后再回看,两相对比,高下立判! 下面谨将另一种解法也列出,读者可以自行对比,想必可以对法一的优越性有更深刻的理解。
#include<stdio.h>
int main()
{int i,j,k,n,d,a[20][20]={0},di[4]={0,1,0,-1},dj[4]={1,0,-1,0};
scanf("%d",&n);
for(i=j=d=k=0;k<n*n;)
{a[i][j]=++k;
if(j==n-1&&d==0||i==n-1&&d==1||j==0&&d==2||a[i+di[d]][j+dj[d]]>0)d=(d+1)%4;
i+=di[d];
j+=dj[d];
}
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
if(j==0)
printf("%2d",a[i][j]);
else
printf(" %2d",a[i][j]);
}
printf("\n");
}
return 0;
}
万万没想到,写完这题的解答时,第二次机考已经成为了过去时。考试不是目的,学习方为根本。不思过往,不畏将来,谨以本文记录编程路上一个新的小起点!共勉。