这是我的第一篇博客,欢迎大家给予建议。
前言
对于2022C语言的期中机试,总体来说难度不大,但较往年而言难度还是加大了些。如有错误和更好解法,欢迎批评指正。
提示:以下是本篇文章正文内容
1.卡牌排序(20分)
题目描述
小南有一个习惯,他喜欢将所有卡牌按照牌面数字的奇偶性分类并由小到大排序好,由于他最近实验课非常多,他想让优秀的你帮帮他。
输入
多个样例。每个样例包含2行输入:
第1行输入一个正整数n(2≤n≤10000)表示卡牌数的张数,第2行输入n个正整数ai (ai 满足int类型范围)表示卡牌牌面上的数字,奇数和偶数的个数大于等于1。
输出
每个样例输出2行,第1行是由小到大排序好的奇数数字卡牌,第2行是由小到大排序好的偶数数字卡牌,数字之间用1个空格分开。每两个样例的输出结果之间用1个空行分开。
样例输入 Copy
5
1 6 9 7 2
2
6 101
样例输出 Copy
1 7 9
2 6
101
6
代码如下(示例):
#include<stdio.h>
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
int a[10000];
int i,j,m,t,x;
for(i=0;i<n;i++)
{
scanf("%d",&a[i]);
}
for (i = 0; i < n - 1; i++) {
for (j = i + 1; j > 0; j--) {
if (a[j] < a[j - 1]) {
a[j] = a[j] + a[j - 1];
a[j - 1] = a[j] - a[j - 1];
a[j] = a[j] - a[j - 1];
} else
break;
}
}
for (i = 0; i < n; i++)
{
if(a[i]%2!=0)
printf("%d ",a[i]);
}
printf("\n");
for (i = 0; i < n; i++)
{
if(a[i]%2==0)
printf("%d ",a[i]);
}
printf("\n");
printf("\n");
}
return 0;
}
2.小南找书(20分)
题目描述
小南热心志愿者活动,有时间的时候会在图书馆帮忙整理书籍。图书馆有一个很大的书架,书架一共有n(1≤n≤103)层,第i层上放了ai (1 ≤ ai ≤ 103)本书。每本书用连续的数字进行了编号:第1层书架上的书从1号到a1号,第2层放的书是从a1+1号到a1 + a2号,以此类推。
例如:当n等于2,a1为1,a2为3时,第1层书架上的1本书编号为1,第2层书架上的3本书编号依次为2、3、4。
小南想让你帮他编程实现,对于给定的书的编号,快速找到这本书在书架的第几层上。
说明:数组定义时如果长度大于106,有些编译器需要定为外部变量。
输入
多个样例。 每个样例输入包括4行:
第1行输入一个整数n (1≤n≤ 103),代表书架的层数。
第2行输入n个整数a1, a2, ..., an (1≤ai ≤103,a1+a2+...+ an ≤106),其中ai代表第i层书架上的书的数量。
第3行输入一个整数m (1≤m≤103)代表小南要找的书的数量。
第4行输入m个整数b1, b2, ...,bm(1 ≤ bi ≤a1+a2+...+ an),分别表示小南要找的m本书的编号。
输出
每个样例输出m行,第i行包含一个整数,代表编号为 bi的书所在的书架的层数。
样例输入 Copy
2
1 3
2
1 3
5
1 8 3 5 8
3
1 24 11
样例输出 Copy
1
2
1
5
3
代码如下(示例):
#include<stdio.h>
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
int i,m,j;
int a[1001]={0};
int b[1001]={0};
int sum=0;
for(i=0;i<n;i++)
{
scanf("%d",&a[i]);
}
scanf("%d",&m);
for(j=0;j<m;j++)
{
scanf("%d",&b[j]);
for(i=0;i<n;i++)
{
sum+=a[i];
if(b[j]<=sum)
{
printf("%d\n",i+1);
sum=0;
break;
}
}
}
}
return 0;
}
3.时钟加法(20分)
题目描述
小南最近迷上了各种形式的加法,例如时钟加法,时钟加法是指给定一个当前时间,其形式为h:m:s,计算加上n秒后新的时间。你能帮他编程实现吗?
输入
多个样例。每个样例输入1行形式为h:m:s+n的数据,其中h(0≤h≤23)代表小时,m(0≤m≤59)代表分钟,s(0≤s≤59)代表秒钟,n(1≤n≤105)代表经过的秒数。
输出
每个样例输出新的时间,形式为h:m:s。每个样例输出结果占一行。
样例输入 Copy
0:0:0+360
23:29:59+1801
7:8:15+1
样例输出 Copy
00:06:00
00:00:00
07:08:16
代码如下(示例):
#include<stdio.h>
int main()
{
int h,m,s;
long long int n=0;
int sum=0;
int cnt=0;
int shi,fen,miao;
while(scanf("%d:%d:%d+%lld",&h,&m,&s,&n)!=EOF)
{
sum=h*3600+m*60+s;
cnt=sum+n;
shi=cnt/3600;
fen=(cnt-shi*3600)/60;
miao=cnt-shi*3600-fen*60;
while(shi>=24)
shi=shi-24;
if(miao==60)
fen++;
if(fen==60)
shi++;
printf("%02d:%02d:%02d\n",shi,fen,miao);
}
return 0;
}
4.地铁出行(20分)
题目描述
长沙地铁票有两种优惠方式,一种是月票,价格为100元;一种是消费打折,打折的规则为:本次乘车前总消费不足 10 元本次不打折,满 10 元不足 15 元本次打8 折,满 15 元不足 40 元本次打 5 折,已满 40 元后本次不打折。
例如:小南11月份乘坐了3次地铁,原价分别是10元、8元、2元,则第1次由于前面的消费为0元,因此不打折,小南花费10元;第2次的时候由于前面消费满了10元,因此8元的原票价打8折,即花费6.4元;第3次消费的时候前面累计消费了16.4元,因此2元的原票价打5折,即花费1元。那么小南11月份的实际地铁出行费用是17.4元。
小南在2022年买的是地铁月票,已知小南某月出行的次数和每次出行的原票价,请问他购买月票的决定是否正确?即消费打折后的实际地铁出行费用大于等于月票价格,则认定为正确,否则认定为不正确。
输入
多个样例。 每个样例输入包含2行:
第1行一个整数n(1≤n≤100)代表小南某月出行的次数,第2行 n 个正整数ai (1 ≤ ai ≤ 50)代表每次出行的原票价,小南是按照输入顺序依次出行的。
输出
对于每个样例,如果小南购买月票的决定正确就输出Yes,否则输出No。每个样例结果输出占一行。
样例输入 Copy
3
10 8 2
8
10 10 10 20 20 20 20 20
样例输出 Copy
No
Yes
代码如下(示例):
#include<stdio.h>
int main()
{
int T;
while(scanf("%d",&T)!=EOF)
{
double a[105];
int i;
double sum=0;
for(i=0;i<T;i++)
{
scanf("%lf",&a[i]);
if(sum<10)
sum+=a[i];
else if(sum>=10 && sum<15 && i>=1)//i=1加不加都行
sum+=a[i]*0.8;
else if(sum>=15 && sum<40 && i>=1)
sum+=a[i]*0.5;
else
sum+=a[i];
}
if(sum>=100)
printf("Yes\n");
else
printf("No\n");
}
return 0;
}
5.出线概率(10分)
题目描述
2022世界杯正在火热进行中,小南是足球球迷,想知道某个球队的出线概率。经过严肃认真的研究,他发现其出线概率是一种可以计算的玄学:根据球队的名字可以得到出线概率!球队的名字由n(1≤n≤30)个小写字母c1, c2, ..., cn组成,小写字母只包括'a'~'i',其编号分别对应1~9,则出线概率的计算公式为:
((-1)1*(c1对应的编号)*101 +(-1)2*(c2对应的编号)*102 + ... (-1)n*(cn对应的编号)*10n )/10n+1
最终结果保留到小数点后n位。例如当球队名字为fff时,f字母对应的编号是6,则出线概率为:(-60+600-6000)/10000=-0.546。
给定某个球队的名字,请你帮助小南计算一下该球队出现在下次世界杯的概率吧!注意有些球队的名字组成很长哦,最大可达30位呢。
输入
多个样例。每个样例输入1行包含一个由小写字母组成的字符串(小写字母只包括'a'~'i'),表示球队的名字,长度为n(1≤n≤30)。
输出
每个样例输出一个实数表示出线概率,保留到小数点后n位。
样例输入 Copy
fff
aaaa
样例输出 Copy
-0.546
0.0909
代码如下(示例):
#include <stdio.h>
#include <string.h>
int main() {
char sen[36];
while (scanf("%s", sen) != EOF) {
int length = strlen(sen);
char ans1[length + 2];
char ans2[length + 2];
int r1 = 0, r2 = 0;
for (int i = 0; sen[i] != 0; i++) {
if (i % 2 == 0) {
ans1[r1++] = sen[i] - 'a' + '1';
ans2[r2++] = '0';
} else {
ans1[r1++] = '0';
ans2[r2++] = sen[i] - 'a' + '1';
}
}
ans1[r1++] = '\0';
ans2[r2++] = '\0';
char ans3[length + 5];
int r3 = 0, temp = 0;
if (length % 2 == 0) {
for (int i = 0; ans1[i] != 0; i++) {
if (ans2[i] - temp >= ans1[i]) {
ans3[r3++] = '0' + (ans2[i] - '0' - ans1[i] + '0' - temp);
temp = 0;
} else {
ans3[r3++] = '0' + (ans2[i] + 10 - '0' - ans1[i] + '0' - temp);
temp++;
}
}
} else {
for (int i = 0; ans1[i] != 0; i++) {
if (ans1[i] - temp >= ans2[i]) {
ans3[r3++] = '0' + (ans1[i] - '0' - ans2[i] + '0' - temp);
temp = 0;
} else {
ans3[r3++] = '0' + (ans1[i] + 10 - '0' - ans2[i] + '0' - temp);
temp++;
}
}
}
ans3[r3] = '\0';
if (length % 2 == 0)
printf("0.");
else
printf("-0.");
for (int i = r3 - 1; i >= 0; i--) {
printf("%c", ans3[i]);
}
printf("\n");
}
return 0;
}
#include<stdio.h>//80%
#include<math.h>
#include<string.h>
int main()
{
char n[35];
while(scanf("%s",&n)!=EOF)
{
long double gai=0.0;
long double gailv=0.0;
int len,i;
int bian=0;
len=strlen(n);
for(i=0;i<len;i++)
{
if(n[i]=='a')
bian=1;
else if(n[i]=='b')
bian=2;
else if(n[i]=='c')
bian=3;
else if(n[i]=='d')
bian=4;
else if(n[i]=='e')
bian=5;
else if(n[i]=='f')
bian=6;
else if(n[i]=='g')
bian=7;
else if(n[i]=='h')
bian=8;
else
bian=9;
gai+=pow(-1,i+1)*bian*pow(10,i+1);
}
gailv=(double)gai/pow(10,len+1);
printf("%.*Lf\n",len,gailv);
}
return 0;
}
6.填数游戏(10分)
题目描述
小南是个素数爱好者,设计了一种与素数有关的填数游戏。该游戏的要求是:输入一个长度为n(1≤n≤10000)的数字串(由数字1~9组成,没有数字0)和一个正整数m(1≤m≤4),将数字串从左边开始,每取m位数字构成一个整数保存起来,剩余的不够m位的也构成一个整数。接下来,他将这些整数ai 按照以下四种特性进行分类:
(1)1类:整数ai 是素数,素数是指除了1和本身外不能被其他数整除的正整数,2是最小的素数。
(2)2类:整数ai 组成的各位数字之和是素数,如整数11的数字之和为2,是素数,满足该条件。
(3)3类:整数ai 组成的各位数字中至少有一个是素数,如整数123中,有素数数字2,满足该条件。
(4)4类:不满足前3类的其他整数。
数据分类按照1类、2类、3类和4类的顺序进行。例如整数223虽然满足1类、2类和3类特性,按照顺序归入1类;25满足2类和3类特性,按照顺序归入2类。接下来小南将这4类整数分别填入一个k*k的方阵中,k为奇数,满足3≤k≤101。该方阵用星号“*”分割成上三角形、左三角形、下三角形和右三角形四个部分,上三角形填入1类整数、左三角形填入2类整数、右三角形填入3类整数、下三角形填入4类整数。填数的过程按照整数出现的顺序从上到下从左至右进行,如果填不满则填充数字0,每个数据输出占5位,右对齐,方阵k的选择要求所有数据都可以按照要求填入且填入的0的个数最少。
说明:当输入的n位数字串为123456789123456789,输入的m为2时,整数分割情况如下:
1类整数:23、67、89
2类整数:12、34、56
3类整数:78、45
4类整数:91
选定的k为5时的填充情况如图1所示,选定的k为7时的填充情况如图2所示。根据题目要求填入的0的个数最少,则图1是正确的结果。
现有给定的n位数字串和正整数m,请你帮助小南编程实现输出正确的填充结果。
输入
多个样例。 每个样例输入一行包含一个n(1≤n≤10000)位数字串(由数字1~9组成,没有数字0)和正整数m(1≤n≤4) 。
输出
每个样例按照填充要求输出一个正确的方阵图。输出的整数和星号“*”的位数都是5位,右对齐。每两个样例的输出结果之间用一个空行分开。
样例输入 Copy
123456789123456789 2
1234567 1
样例输出 Copy
* 23 67 89 *
12 * 0 * 78
34 56 * 45 0
0 * 91 * 0
* 0 0 0 *
* 2 3 5 *
0 * 7 * 0
0 0 * 0 0
0 * 1 * 0
* 4 6 0 *
代码如下(示例):
#include <stdio.h>
#include <string.h>
int zhishu(int a) {
if (a < 2)
return 0;
else if (a == 2)
return 1;
else {
for (int i = 2; i < a; i++) {
if (a % i == 0)
return 0;
}
}
return 1;
}
int panduan2(int a) {
int sum = 0;
while (a > 0) {
sum = sum + a % 10;
a /= 10;
}
if (zhishu(sum))
return 1;
else
return 0;
}
int panduan3(int a) {
while (a > 0) {
int t = a % 10;
a /= 10;
if (zhishu(t) )
return 1;
}
return 0;
}
int main() {
char sen[10086];
int m;
while (scanf("%s %d", sen, &m) != EOF) {
int length = strlen(sen);
int num = length / m + 1;
int ass[num + 5];
int way = 0;
int temp = 0;
int r = 0;
for (int i = 0; sen[i] != 0; i++) {
if (way < m) {
temp = temp * 10 + sen[i] - '0';
way++;
} else {
i--;
ass[r++] = temp;
temp = 0;
way = 0;
}
}
if (way != 0) {
ass[r++] = temp;
}
int ans1[r], ans2[r], ans3[r], ans4[r];
int r1 = 0, r2 = 0, r3 = 0, r4 = 0;
for (int i = 0; i < r; i++) {
if ((zhishu(ass[i]))) {
ans1[r1++] = ass[i];
} else if (panduan2(ass[i])) {
ans2[r2++] = ass[i];
} else if (panduan3(ass[i])) {
ans3[r3++] = ass[i];
} else {
ans4[r4++] = ass[i];
}
}
int k = 3;
int ling = 0;
int max = r1 > r2 ? r1 : r2;
max = max > r3 ? max : r3;
max = max > r4 ? max : r4;
for (k = 3; k <= 101; k++) {
if (k % 2 == 0)
continue;
int all = k * k, left = all - k - k + 1;
ling = left - r1 - r2 - r3 - r4;
left /= 4;
if (left >= max)
break;
}
int ar1 = 0, ar2 = 0, ar3 = 0, ar4 = 0;
for (int i = 0; i < k; i++) {
for (int j = 0; j < k; j++) {
if (j == i || j == k - i - 1)
printf(" *");
else {
if (i < (k / 2)) {
if (j < i) {
if (ar2 < r2)
printf("%5d", ans2[ar2++]);
else
printf(" 0");
} else if (j > k - i - 1) {
if (ar3 < r3)
printf("%5d", ans3[ar3++]);
else
printf(" 0");
} else if (ar1 < r1)
printf("%5d", ans1[ar1++]);
else
printf(" 0");
} else {
if (j < k - i - 1) {
if (ar2 < r2)
printf("%5d", ans2[ar2++]);
else
printf(" 0");
} else if (j > i) {
if (ar3 < r3)
printf("%5d", ans3[ar3++]);
else
printf(" 0");
} else if (ar4 < r4)
printf("%5d", ans4[ar4++]);
else
printf(" 0");
}
}
}
printf("\n");
}
printf("\n");
}
return 0;
}
总结
时钟加法一定要记得用while,否则是60%。
出现概率需要用到字符串输出大整数,单靠精度是没有办法AC的,只能达到80%。