PTA - C语言国庆题集3

7-41 单词翻转(字符串分割、字符串拷贝、字符串翻转)

从键盘输入一个字符串,包含很多个单词。每个单词之间以1个或多个空格隔开。要求翻转每个单词,但是单词在句子中的顺序不变。注意行前和行后可能有多个空格。

输入格式:
一个字符串,包含很多个单词。每个单词之间以1个或多个空格隔开。要求翻转每个单词,但是单词在句子中的顺序不变。注意行前和行后可能有多个空格。字符串总长度不超过1000,单词数不超过50,每个单词不超过20个字母。测试数据保证输入的字符只含英文字母和空格。
输出格式:
输出翻转后的字符串。每个单词之后输出一个空格。注意行前不能有多余的空格。行末只能有1个空格。

输入样例1:
olleH dlroW
输出样例1:
Hello World
输入样例2:
I ma a tneduts
输出样例2:
I am a student

#include <stdio.h>
#include <string.h>

char s[1009];
char ans[51][21];// 用来存分割的字符串数组
int index=0;
void reverse(char* s){
    int l=0,r=strlen(s)-1;
    while(l<r){
        char tmp=s[l];
        s[l]=s[r];
        s[r]=tmp;
        l++,r--;
    }
}
int main(){
    scanf(" %[^\n]",s);
    // puts(s);
    char* temp=strtok(s," ");
    while(temp!=NULL){
        strcpy(ans[index++],temp);
        temp=strtok(NULL," ");
    }
    for(int i=0;i<index;i++){
        reverse(ans[i]);
        printf("%s ",ans[i]);
    }
    return 0;
}

7-42 括号匹配(C++栈)

假设表达式中只包含三种括号:圆括号、方括号和花括号,它们可相互嵌套,如([{}])或({[][()]})等均为正确的格式,而{[]})}或{[()]或([]}均为不正确的格式.
输入一串括号
如果输入的右括号多余,输出:Extra right brackets;
如果输入的左括号多余, 输出:Extra left brackets;
如果输入的括号不匹配,输出:Brackets not match;
如果输入的括号匹配,输出:Brackets match

输入格式:
一行只含 ( ) [ ] { } 这6种字符,不含其它任何字符的字符串。字符串不超过1000个字符。
输出格式:
如果输入的右括号多余,输出:
Extra right brackets
如果输入的左括号多余, 输出:
Extra left brackets
如果输入的括号不匹配,输出:
Brackets not match
如果输入的括号匹配,输出:
Brackets match

输入样例:
{{{{)))
输出样例:
Brackets not match

#include <iostream>
#include <stack>
#include <string>

bool isLeftBracket(char bracket) {
    return bracket == '(' || bracket == '[' || bracket == '{';
}

bool isRightBracket(char bracket) {
    return bracket == ')' || bracket == ']' || bracket == '}';
}

bool isMatching(char left, char right) {
    return (left == '(' && right == ')') || (left == '[' && right == ']') || (left == '{' && right == '}');
}

std::string checkBrackets(const std::string& input) {
    std::stack<char> bracketStack;

    for (char bracket : input) {
        if (isLeftBracket(bracket)) {
            bracketStack.push(bracket);
        } else if (isRightBracket(bracket)) {
            if (bracketStack.empty()) {
                return "Extra right brackets";
            } else {
                char top = bracketStack.top();
                bracketStack.pop();
                if (!isMatching(top, bracket)) {
                    return "Brackets not match";
                }
            }
        }
    }

    if (!bracketStack.empty()) {
        return "Extra left brackets";
    }

    return "Brackets match";
}

int main() {
    std::string input;
    std::cin >> input;

    std::cout << checkBrackets(input) << std::endl;

    return 0;
}

7-43 汉诺塔问题(Hanoi)

一、汉诺塔问题
有三根杆子A,B,C。A杆上有N个(N>1)穿孔圆盘,盘的尺寸由下到上依次变小。要求按下列规则将所有圆盘移至C杆: 每次只能移动一个圆盘; 大盘不能叠在小盘上面。 提示:可将圆盘临时置于B杆,也可将从A杆移出的圆盘重新移回A杆,但都必须遵循上述两条规则。
问:如何移?最少要移动多少次?
汉诺塔示意图如下:
图例
二、故事由来
法国数学家爱德华·卢卡斯曾编写过一个印度的古老传说:在世界中心贝拿勒斯(在印度北部)的圣庙里,一块黄铜板上插着三根宝石针。印度教的主神梵天在创造世界的时候,在其中一根针上从下到上地穿好了由大到小的64片金片,这就是所谓的汉诺塔。不论白天黑夜,总有一个僧侣在按照下面的法则移动这些金片:一次只移动一片,不管在哪根针上,小片必须在大片上面。僧侣们预言,当所有的金片都从梵天穿好的那根针上移到另外一根针上时,世界就将在一声霹雳中消灭,而梵塔、庙宇和众生也都将同归于尽。
不管这个传说的可信度有多大,如果考虑一下把64片金片,由一根针上移到另一根针上,并且始终保持上小下大的顺序。这需要多少次移动呢?这里需要递归的方法。假设有n片,移动次数是f(n).显然f(1)=1,f(2)=3,f(3)=7,且f(k+1)=2f(k)+1。此后不难证明f(n)=2n-1。n=64时, 假如每秒钟一次,共需多长时间呢?一个平年365天有31536000 秒,闰年366天有31622400秒,平均每年31556952秒,计算一下: 18446744073709551615秒 这表明移完这些金片需要5845.54亿年以上,而地球存在至今不过45亿年,太阳系的预期寿命据说也就是数百亿年。真的过了5845.54亿年,不说太阳系和银河系,至少地球上的一切生命,连同梵塔、庙宇等,都早已经灰飞烟灭。
三、解法
解法的基本思想是递归。假设有A、B、C三个塔,A塔有N块盘,目标是把这些盘全部移到C塔。那么先把A塔顶部的N-1块盘移动到B塔,再把A塔剩下的大盘移到C,最后把B塔的N-1块盘移到C。 每次移动多于一块盘时,则再次使用上述算法来移动。

输入格式:
输入为一个整数后面跟三个单字符字符串。
整数为盘子的数目,后三个字符表示三个杆子的编号。
输出格式:
输出每一步移动盘子的记录。一次移动一行。
每次移动的记录为例如3:a->b 的形式,即把编号为3的盘子从a杆移至b杆。
我们约定圆盘从小到大编号为1, 2, …n。即最上面那个最小的圆盘编号为1,最下面最大的圆盘编号为n。

输入样例:
3 a b c
输出样例:
1:a->c
2:a->b
1:c->b
3:a->c
1:b->a
2:b->c
1:a->c

#include <stdio.h>

void hanoi(int n,char from,char to,char aux){
    if(n==1){
        printf("%d:%c->%c\n",n,from,to);
        return;
    } 
    // 将 源柱子from上前n-1块 通过 目标柱to 移动到 辅助柱aux
    hanoi(n-1,from,aux,to); 
    // 将 第n块 移动到 目标柱to
    printf("%d:%c->%c\n",n,from,to);
    // 将 辅助柱aux上前n-1块 通过 源柱子from 移动到 目标柱to
    hanoi(n-1,aux,to,from); 
}
int main(){
    int n;
    char a,b,c;scanf("%d %c %c %c",&n,&a,&b,&c);
    hanoi(n,a,c,b); // 源柱子a,目标柱c,辅助柱b
    return 0;
}

7-44 判断10的倍数

输入一个整数a,如果a为10的倍数,则输出a;如果a不是10的倍数,什么也不输出。

输入格式:
直接输入1个整数,没有其他任何附加字符。
输出格式:
直接输出结果,没有其他任何附加字符。

输入样例:
在这里给出一组输入。例如:
20
输出样例:
在这里给出相应的输出。例如:
20

#include <stdio.h>
int main(){
    int n;scanf("%d",&n);
    if(n%10==0) printf("%d",n);
    return 0;
}

7-45 求5个整数中的最小数

从键盘输入5个整数,输出其中的最小数。

输入格式:
输入5个整数。
输出格式:
输入的5个整数中的最小数。

输入样例:
在这里给出一组输入。例如:
5 2 1 7 3
输出样例:
在这里给出相应的输出。例如:
1

#include <stdio.h>

int main(){
    int a[5];
    for(int i=0;i<5;i++) scanf("%d",&a[i]);
    int min=a[0];
    for(int i=1;i<5;i++) {
        if(a[i]<min) min=a[i];
    }
    printf("%d",min);
    return 0;
}

7-46 求n个数中的最大值

用户先输入一个正整数N(N不超过10),表示将下来将输入N个整数(均为int型),请在这N个整数中找出最大值。

输入格式:
输入为一行,第一个是正整数N,然后是N个整数。
输出格式:
输出为一个整数,表示N个整数中的最大值。

输入样例1:
4 2 123 -100 0
输出样例1:
123
输入样例2:
3 -9 -18 -28
输出样例2:
-9

#include <stdio.h>

int a[16];
int main(){
    int n;scanf("%d",&n);
    for(int i=0;i<n;i++) scanf("%d",&a[i]);
    int max=a[0];
    for(int i=1;i<n;i++) {
        if(a[i]>max) max=a[i];
    }
    printf("%d",max);
    return 0;
}

7-47 一批数中最大值最小值

从键盘输入若干学生的成绩,统计并输出最高成绩和最低成绩,当输入负数时循环结束。

输入格式:
在一行中输入若干个用空格间隔的整数,最后输入负数结束输入,数据之间只能用1个空格间隔。
输出格式:
在一行中按照“max=最高分,min=最低分”的格式输出结果,最高分和最低分均原样输出,没有列宽控制。

输入样例1:
58 78 95 65 86 -1
输出样例1:
max=95,min=58
输入样例2:
9 8 6 7 0 -21
输出样例2:
在这里给出相应的输出。例如:
max=9,min=0

#include <stdio.h>

int a[10009];
int main(){
    int n=0;
    while(scanf("%d",&a[n]) && a[n]>=0) n++;
    int max=a[0],min=a[0];
    for(int i=1;i<n;i++) {
        if(a[i]>max) max=a[i];
        if(a[i]<min) min=a[i];
    }
    printf("max=%d,min=%d",max,min);
    return 0;
}

7-48 计算平方和

编写一个程序,要求用户输入一个下限整数和一个上限整数,然后,依次计算从下限到上限的每一个数的平方的和,最后显示结果。程序将不断要求用户输入下限整数和上限整数并显示出答案,直到用户输入的上限整数等于或小于下限整数为止。

输入格式:
程序将不断要求用户输入下限整数和上限整数并显示出答案,直到用户输入的上限整数等于或小于下限整数为止。
每次输入一对整数,分别是下限和上限。当输入的上限等于或小于下限时结束。
输出格式:
从下限到上限的每个整数的平方和。

输入样例1:
5 9
3 25
5 3
输出样例1:
The sum of the squares from 25 to 81 is 255
The sum of the squares from 9 to 625 is 5520
Done
输入样例2:
9 7
输出样例2:
Done

#include <stdio.h>

int main(){
    int a,b;
    while(scanf("%d %d",&a,&b) && a<b){
        int sum=0;
        for(int i=a;i<=b;i++) {
            sum += i*i;
        }
        printf("The sum of the squares from %d to %d is %d\n",a*a,b*b,sum);
    }
    printf("Done\n");
    return 0;
}

7-49 毕达哥拉斯三元组

一个直角三角形具有边长均为整数的三条边。直角三角形边长的这组整数值称为毕达哥拉斯三元组(中国称为勾股数)。这三条边必须满足这样的关系:两条直角边的平方之和必须等于直角三角形斜边的平方。从键盘输入一个正整数n,请找出不大于n的所有毕达哥拉斯三元组。可以使用一个三重嵌套的for循环语句,它可以非常简单地尝试所有的可能性。这是一个穷举法的典型例子。
对于很多人来说,这种技术并不美观,也不令人愉快。但有很多理由可以说明为什么这种技术是重要的。首先,随着计算功能显著增强,几年前使用这种技术,需要几年甚至几个世纪的计算时间才能够得到结果的解决方案,现在能够在几个小时、几分钟甚至几秒之内就得到结果。其次,在以后的计算机科学课程中,你将学到,除了使用穷举法之外,有大量的有趣问题无法用更高效的算法来解决。

输入格式:
输入一个正整数n。
输出格式:
以(a, b, c)的形式,按字典顺序输出不大于n的所有毕达哥拉斯三元组。每个三元组占一行。注意每个逗号后面有一个空格,括号前后均没有空格。

输入样例1:
10
输出样例1:
(3, 4, 5)
(4, 3, 5)
(6, 8, 10)
(8, 6, 10)
输入样例2:
20
输出样例2:
(3, 4, 5)
(4, 3, 5)
(5, 12, 13)
(6, 8, 10)
(8, 6, 10)
(8, 15, 17)
(9, 12, 15)
(12, 5, 13)
(12, 9, 15)
(12, 16, 20)
(15, 8, 17)
(16, 12, 20)

#include <stdio.h>

int main(){
    int n;scanf("%d",&n);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            for(int k=1;k<=n;k++){
                int sum=i+j+k;
                int max=(i>j?i:j)>k?(i>j?i:j):k;
                int min=(i<j?i:j)<k?(i<j?i:j):k;
                if((min*min+(sum-max-min)*(sum-max-min))==max*max && (k>i && k>j))
                    printf("(%d, %d, %d)\n",i,j,k);
            }
        }
    }
    return 0;
}

7-50 计算一组x和y

输入30个整数a1,a2,a3,…,a30,计算所有的x与y。已知:
请添加图片描述
输入格式:
30个整数
输出格式:
计算得到的x1, x2,…,x10
计算得到的y1, y2,…,y10
所有输出精确到小数点后3位。
注意:
1、输出的每个“=”左右各有一个空格,输出的每个“,”后有一个空格。
2、输出的所有符号必须是用英文输入法输入的符号。

输入样例:
29 62 4 44 42 4 79 47 45 39 98 58 38 72 66 91 85 29 58 70 89 11 58 65 5 39 47 3 85 33
输出样例:
在这里给出相应的输出。例如:
x[1] = 39.250, x[2] = 33.000, x[3] = 54.500, x[4] = 73.250, x[5] = 62.000, x[6] = 72.500, x[7] = 71.750, x[8] = 48.000, x[9] = 32.500, x[10] = 51.500,
y[1] = 9.765, y[2] = 90.862, y[3] = 0.316, y[4] = 28.722, y[5] = 24.818, y[6] = 0.220, y[7] = 60.412, y[8] = 94.000, y[9] = 8.534, y[10] = 49.586,

#include <stdio.h>

int a[31];
int main(){
    for(int i=1;i<=30;i++) scanf("%d",&a[i]);
    // for(int i=1;i<=30;i++) printf("%d ",a[i]);
    int cnt=1;
    for(int i=1;i<=30;i+=3){
        printf("x[%d] = %.3f, ",cnt++,(double)(a[i]+2*a[i+1]+a[i+2])/4);
    }
    printf("\n");
    cnt=1;
    for(int i=1,j=30,k=11;i<=10;i++,j--,k++){
        printf("y[%d] = %.3f, ",cnt++,(double)a[i]*a[j]/a[k]);
    }
    return 0;
}

7-51 筛法求素数(ola筛)

素数是仅仅能被它本身和1整除的任何整数。筛法求素数是一种查找素数的方法。它的算法如下:
1、创建一个数组,并将所有元素初始化为1(真)。具有素数下标的数组元素将保持为1,而其它数组元素最终将被设置为0。
2、从数组下标2开始,每次找到一个值是1的数组元素时,在数组的剩余部分中循环,并将值为1的元素的下标整数倍的所有元素设置为0。对于数组下标2,数组中所有2以上的而且是2的整数倍的元素都将这是为0(下标4、6、8、10等等)。对于数组下标3,数组中所有3以上,而且是3的整数倍的元素都将设置为0(下标6、9、12、15等等)。
当这个过程结束时,仍然为1的数组元素的下标是一个素数。然后就可以输出这些素数。
编写一个程序,输出区间[m, n]之间的所有素数。

输入格式:
输入的第一行是一个整数k,表示以后会有k次查询。
后面的k行中,每行2个整数m和n。
输入保证 2 <= m <= n <= 100000。
输出格式:
对每一行的m和n,把闭区间[m, n]之间的所有素数输出到一行。每个数之间以空格隔开。若区间内没有素数,输出None

输入样例:
6
2 20
3 3
5 15
11 32
121 126
100 200
输出样例:
在这里给出相应的输出。例如:
2 3 5 7 11 13 17 19
3
5 7 11 13
11 13 17 19 23 29 31
None
101 103 107 109 113 127 131 137 139 149 151 157 163 167 173 179 181 191 193 197 199

// #include <stdio.h>

// int isprime(int x){
//     if(x<=3) return 1;
//     if(x%2==0 || x%3==0) return 0;
//     for(int i=5;i*i<=x;i+=6)
//         if(x%i==0 || x%(i+2)==0) return 0;
//     return 1;
// }
// int main(){
//     int t;scanf("%d",&t);
//     int m,n,flag=0;
//     while(t--){
//         flag=0;
//         scanf("%d %d",&m,&n);
//         for(int i=m;i<=n;i++)
//             if(isprime(i)) printf("%d ",i),flag=1;
//         if(!flag) printf("None");
//         printf("\n");
//     }
//     return 0;
// }

// #include <stdio.h>
// #include <stdlib.h>
// #include <string.h>

// int pri[100009]; // 0表示未筛
// int primes[100009],pp=0;
// void ola(int m,int n){
//     for(int i=2;i<=n;i++){ // 遍历数字,从2开始筛
//         if(!pri[i]) primes[++pp]=i;// 存素数
//         for(int j=1;j<=pp && primes[j]*i<=n;j++){ // 筛掉素数的倍数
//             pri[primes[j]*i]=1;
//             if(i%primes[j]==0) break;
//         }
//     }
// }
// int main(){
//     int t;scanf("%d",&t);
//     int m,n,flag=0;
//     while(t--){
//         flag=0;
//         memset(pri,0,sizeof(pri));
//         memset(primes,0,sizeof(primes));
//         pp=0;
//         scanf("%d %d",&m,&n);
//         ola(m,n);
//         for(int i=1;i<=pp;i++) {
//             if(primes[i]>=m) // 直到大于等于m,才开始输出素数
//                 printf("%d ",primes[i]),flag=1;
//         }
//         if(!flag) printf("None");
//         printf("\n");
//     }
//     return 0;
// }

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int pri[100009]; // 0表示未筛除
int primes[100009],pp=0;
void ola(int m,int n){
    for(int i=2;i<=n;i++){
        if(!pri[i]) primes[++pp]=i;
        for(int j=1;j<=pp && primes[j]*i<=n;j++) {// 删掉已保留素数的倍数
            pri[primes[j]*i]=1;
            if(i%primes[j]==0) break;
        }
    }
}
int main(){
    int t;scanf("%d",&t);
    while(t--){
        int m,n,flag=0;
        pp=0;// 素数的个数
        memset(pri,0,sizeof(pri));
        memset(primes,0,sizeof(primes));
        scanf("%d %d",&m,&n);
        ola(m,n);
        for(int i=1;i<=pp;i++) {
            if(primes[i]>=m)
                printf("%d ",primes[i]),flag=1;
        }
        if(!flag) printf("None");
        printf("\n");
    }
    return 0;
}

7-52 完美的素数

一个十进制数,如果是素数,而且它的各位数字和也是素数,则称之为“美素数”,如29,本身是素数,而且2+9 = 11也是素数,所以它是美素数。从键盘输入一系列正整数,输入以0结束。按输入顺序输出这些数中的美素数。数据保证输入序列中至少有1个美素数。

输入格式:
从键盘输入一系列正整数,输入 0 表示输入结束。
输出格式:
按输入顺序输出这些数中的美素数。每个数占一行。

输入样例:
在这里给出一组输入。例如:
11 12 13 17 19 21 23 0
输出样例:
在这里给出相应的输出。例如:
11
23

#include <stdio.h>

int isPrime(int a){
    int flag=1;
    // 本身为素数
    for(int i=2;i*i<=a;i++){
        if(a%i==0) {
            flag=0;
            break;
        }
    }
    if(flag){// 各位数字和是素数
        int sum=0;
        while(a){
            int t=a%10;
            sum+=t;
            a/=10;
        }
        for(int i=2;i*i<=sum;i++){
            if(sum%i==0) {
                flag=0;
                break;
            }
        }
    }else 
        return flag;
    return flag;
}
int a[109];
int main(){
    int n=0;
    while(scanf("%d",&a[n]) && a[n]!=0) n ++;
    // 遍历
    // for(int i=0;i<n;i++) printf("%d ",a[i]);
    for(int i=0;i<n;i++){
        if(isPrime(a[i])) printf("%d\n",a[i]);
    }
    return 0;
}

7-53 位运算(审题)

输入两个无符号短整型数 a 和 b,输出 a 和 b 按位与、按位或、a 左移 b 位、a 右移 b 位、a 按位取反 的结果。

输入格式:
两个无符号短整型数 a 和 b
输出格式:
用格式控制符"%hu"输出 a 和 b 按位与的结果;
用格式控制符"%hu"输出 a 和 b 按位或的结果;
用格式控制符"%hu"输出 a 左移 b 位的结果;
用格式控制符"%hu"输出 a 右移 b 位的结果;
用格式控制符"%hu"输出 a 按位取反 的结果;
用格式控制符"%hd"输出 a 按位取反 的结果。
注意在所有计算过程中,a 和 b 的值不能改变。
每个输出占1行。

输入样例:
8 3
输出样例:
在这里给出相应的输出。例如:
0
11
64
1
65527
-9

#include <stdio.h>

int main(){
    unsigned short a,b;scanf("%hu %hu",&a,&b);
    printf("%hu\n",a&b);
    printf("%hu\n",a|b);
    printf("%hu\n",a<<b);
    printf("%hu\n",a>>b);
    printf("%hu\n",~a);
    printf("%hd\n",~a);
    return 0;
}

7-54 头插法创建单链表、遍历链表、删除链表(段错误可能是因为创建的数组太小)

输入一系列自然数(0和正整数),输入-1时表示输入结束。按照输入的顺序,用头插法建立单链表,并遍历所建立的单链表,输出这些数据。注意 -1 不加入链表。

输入格式:
第一行是一个正整数k,表示以下会有k组测试数据。
每组测试数据是一系列以空格隔开的自然数(0和正整数)。数列末尾的 -1 表示本组测试数据结束。按照输入的顺序,用头插法建立单链表,并遍历所建立的单链表,输出这些数据。注意 -1 不加入链表。
输出格式:
对于每组测试数据,输出链表中各节点的数据域。每个数据后有一个空格。每组测试数据的输出占1行。

输入样例:
3
1 2 3 4 5 -1
30 20 10 -1
4 2 2 1 1 2 0 2 -1
输出样例:
在这里给出相应的输出。例如:
5 4 3 2 1
10 20 30
2 0 2 1 1 2 2 4
注意:对每组测试数据,创建链表,遍历链表输出之后,一定要删除链表,否则会出现“内存超限”。

#include <stdio.h>
#include <stdlib.h>

int arr[1000009];
int main(){
    int k;scanf("%d",&k);
    int x,index;
    for(int i=0;i<k;i++){
        memset(arr,0,sizeof(arr));
        index=0;
        while(scanf("%d",&x) && x!=-1){
            arr[index++]=x;
        }
        for(int i=index-1;i>=0;i--){
            printf("%d ",arr[i]);
        }
        printf("\n");
    }
    return 0;
}

7-55 合并有序数组(结构体排序)

给定2个非降序序列,要求把他们合并成1个非降序序列。假设所有元素个数为N,要求算法的时间复杂度为O(N)。

输入格式:
输入有4行。
第1行是一个正整数m,表示第2行有m个整数,这些整数构成一个非降序序列,每个整数之间以空格隔开。第3行是一个正整数n,表示第4行有n个整数,这些整数也构成一个非降序序列,每个整数之间以空格隔开。
输出格式:
把第2行的m个整数和第4行的n个整数合并成一个非降序序列,输出这个整数序列。每个数之间隔1个空格。

输入样例:
6
1 3 6 6 8 9
4
2 4 5 7
输出样例:
1 2 3 4 5 6 6 7 8 9
数组大小1e5+9
#define N (int)1e5+9
科学计数法为浮点类型

#include <stdio.h>
#include <stdlib.h>

#define N (int)1e5+9
int a[N];
int b[N];
int ans[2*N];

int cmp(const void* e1,const void* e2){
    return *(int*)e1 - *(int*)e2;
}

int main(){
    int len1;scanf("%d",&len1);
    for(int i=0;i<len1;i++) scanf("%d",&a[i]);
    int len2;scanf("%d",&len2);
    for(int i=0;i<len2;i++) scanf("%d",&b[i]);
    
    int n=0;
    for(int i=0;i<len1;i++) {
        ans[n++]=a[i];
    }
    for(int i=0;i<len2;i++) {
        ans[n++]=b[i];
    }
    qsort(ans,n,sizeof(int),cmp);
    for(int i=0;i<n;i++) printf("%d ",ans[i]);
    return 0;
}

7-57 英雄出场王(C++map)

英雄联盟总决赛正在若火如荼的展开,盲僧、刀妹、酒桶、青钢影等各路英雄悉数登场,当一个英雄被选出场时系统自动登记其序号,出场次数最多的英雄成为出场王。给定英雄序号的出场集合T,例如,T={2,4,4,4,6,7}。其出场王是4号英雄,出场次数为3。对于给定的由n个序号组成的出场集T,计算出场王序号及其出场次数。如果出现多个出场王,请输出序号最小的那个。

输入格式:
输入数据的第1行是英雄出场集T中序号个数n(n<100000000);第二行输入n个出场英雄序号。
输出格式:
输出数据的第1行给出出场王序号,第2行是出场次数。

输入样例1:
6
2 4 4 4 6 7
输出样例1:
4
3
输入样例2:
10
1234568 828 12345 898232689 12345 12345 9876 321 3 12345
输出样例2:
12345
4

#include <bits/stdc++.h>
using namespace std;


int main(){
    int n;cin >> n;
    map<int,int> heros_count;

    //出场王序号及其出场次数。
    // 如果出现多个出场王,请输出(序号最小)的那个
    int num=0,count=0,ans=0;
    for(int i=0;i<n;i++){
        cin >> num;
        heros_count[num]++;
        // 出场次数最多或者出场次数相同并且序号更小
        if(heros_count[num] > count || (heros_count[num]==count && num<ans)){
            ans=num;
            count=heros_count[num];
        }
    }
    cout << ans << '\n';
    cout << count << '\n';
    return 0;
}

7-58 求两个整数的和

本题目要求读入2个整数a和b,然后输出它们的和。

输入格式:
输入在一行中给出2个整数a和b。输入保证在32位整型的取值范围之内。
输出格式:
按示例所示,输出两个整数及它们的和。注意每个数和符号之间有一个空格。

输入样例1:
18 9
输出样例1:
18 + 9 = 27
输入样例2:
3 12
输出样例2:
3 + 12 = 15

#include <stdio.h>

int main(){
    int a,b;scanf("%d %d",&a,&b);
    printf("%d + %d = %d",a,b,a+b);
    return 0;
}

7-59 和是正数、负数还是0?

这是一个编程题模板。
本题目要求读入2个整数a和b,然后输出它们的和,并判断和是正数、负数还是0。

输入格式:
输入在一行中给出2个整数a和b。输入保证在32位整型的取值范围之内。
输出格式:
按示例所示,输出两个整数的和。并输出和是正数、负数还是0。注意数字之后有一个空格。注意单词的第一个字母大写。

输入样例1:
18 9
输出样例1:
27 Positive
输入样例2:
-18 15
输出样例2:
-3 Negative
输入样例3:
147 -147
输出样例3:
0 Zero

#include <stdio.h>

int main(){
    int a,b;scanf("%d %d",&a,&b);
    int sum=a+b;
    printf("%d ",sum);
    if(sum>0) printf("Positive");
    else if(sum<0) printf("Negative");
    else printf("Zero");
    return 0;
}

7-60 区间求和

这是一个编程题模板。
本题目要求读入2个正整数m和n,然后输出闭区间 [m, n] 之间所有奇数的和。

输入格式:
输入在一行中给出2个正整数m和n。输入保证不超过32位整型的表示范围。
输出格式:
输出闭区间 [m, n] 之间所有奇数的和。

输入样例1:
10 15
输出样例1:
39
输入样例2:
21 30
输出样例2:
125
输入样例3:
3 9
输出样例3:
24

#include <stdio.h>

int main(){
    int m,n;scanf("%d %d",&m,&n);
    int sum=0;
    for(int i=m;i<=n;i++){
        if(i%2!=0) sum+=i;
    }
    printf("%d",sum);
    return 0;
}

7-61 找小写字母

本题目要求读入不含空格的字符串,然后输出这个字符串中小写字母的个数。

输入格式:
输入在一行中给出一个不含空格的字符串。输入保证字符串长度不超过100。
输出格式:
输出有两行。
第一行按输入顺序输出这个字符串中所有小写字母。
第二行输出这些小写字母的个数。

输入样例:
AghE+FbcdL@MN
输出样例:
ghbcd
5

#include <stdio.h>
#include <ctype.h>

int main() {
    char str[101];
    char lowercase[101];
    int count = 0;

    // 读入字符串
    fgets(str, sizeof(str), stdin);

    // 遍历字符串,找出小写字母
    for (int i = 0; str[i] != '\0'; i++) {
        if (islower(str[i])) {
            lowercase[count] = str[i];
            count++;
        }
    }

    // 终结字符
    lowercase[count] = '\0';

    // 输出结果
    printf("%s\n", lowercase);
    printf("%d\n", count);

    return 0;
}

7-62 病例统计

某医院想统计一下某项疾病的获得与否与年龄是否有关,需要对以前的诊断记录进行整理,按照0-14、15-18、19-60、61以上(含61)四个年龄段统计的患病人数占总患病人数的比例。

输入格式:
共2行,第一行为过往病人的数目n(0 < n <= 100),第二行为每个病人患病时的年龄。输入保证年龄大于等于0, 小于等于150。
输出格式:
0-14、15-18、19-60、61以上(含61)四个年龄段输出该段患病人数占总患病人数的比例,以小数形式输出,精确到小数点后两位。每个年龄段占一行,共四行。

输入样例:
在这里给出一组输入。例如:
10
1 11 21 31 41 18 61 71 81 91
输出样例:
在这里给出相应的输出。例如:
0.20
0.10
0.30
0.40

#include <stdio.h>

int main(){
    int n;scanf("%d",&n);
    int x;
    int a=0,b=0,c=0,d=0,sum=0;// 4个年龄段的人数
    while(n--){
        scanf("%d",&x);
        if(x>=0 && x<=14) a++;
        else if(x>=15 && x<=18) b++;
        else if(x>=19 && x<=60) c++;
        else d++;
    }
    sum=a+b+c+d;
    printf("%.2f\n%.2f\n%.2f\n%.2f\n",\
           a*1.0/sum,b*1.0/sum,c*1.0/sum,d*1.0/sum);
    return 0;
}

7-63 错误探测

给定一个m行n列的二维数组。
如果每一行偶数的个数是偶数,并且每一列奇数的个数是奇数,认为是正确的,输出yes;否则输出no
注意:0是偶数。

输入格式:
第1行是两个整数m、n。输入保证1 <= m <= 100, 1 <= n <= 200。
接下来输入有m行,每行n个整数。输入保证在32位整型取值范围之内。
输出格式:
如果输入的每一行偶数的个数是偶数,并且每一列奇数的个数是奇数,输出yes;否则输出no

输入样例1:
3 5
1 7 8 9 6
2 7 5 0 7
4 3 8 2 6
输出样例1:
yes
输入样例2:
3 4
1 8 8 9
2 7 5 0
4 3 6 2
输出样例2:
no
输出样例2提示:
输入的第2列
8
7
3
奇数的个数不是奇数,所以输出 no

// 行有偶数个偶数;列有奇数个奇数
// 0是偶数

#include <stdio.h>

int arr[101][201];
int main(){
    int m,n;scanf("%d %d",&m,&n);
    for(int i=0;i<m;i++){
        for(int j=0;j<n;j++) scanf("%d",&arr[i][j]);
    }
    int cnt;
    // 遍历行
    for(int i=0;i<m;i++){
        cnt=0;
        for(int j=0;j<n;j++) {
             if(arr[i][j]%2==0) cnt++; // 当x%2=0时 ,x记为偶数
        }
        if(cnt%2!=0) {
            printf("no");
            return 0;
        }
    }
    // 遍历列
    for(int i=0;i<m;i++){
        cnt=0;
        for(int j=0;j<n;j++) {
            if(arr[j][i]%2!=0) cnt++; // 当x%2!=0时 ,x记为奇数
        }
        if(cnt%2==0) {
            printf("no");
            return 0;
        }
    }
    printf("yes");
    return 0;
}

7-64 素数的和

素数也成为质数,指的是大于1的整数中,只能被1和这个数本身整除的数。
从键盘输入一系列大于1的正整数,输入1时表示输入结束。
求输入的这些正整数中素数的和。

输入格式:
从键盘输入一系列大于1的正整数,输入1时表示输入结束。
输出格式:
输入的这些正整数中素数的和。

输入样例:
10 11 13 9 8 7 1
输出样例:
31
注意:
有可能在输入的所有整数中,一个素数也没有。

#include <stdio.h>

int isPrime(int x){
    if(x<=3) return 1;
    if(x%2==0 || x%3==0) return 0;
    for(int i=5;i*i<=x;i+=6){
        if(x%i==0 || x%(i+2)==0) return 0;
    }
    return 1;
}
int main(){
    int x,sum=0;
    while(1){
        scanf("%d",&x);
        if(x==1) break;
        if(isPrime(x))
            sum+=x;
    }
    printf("%d",sum);
    return 0;
}

7-65 Remove duplicates from a sorted list

Write a program that takes a list sorted in non-decreasing order(非降序) and deletes any duplicate nodes from the list. The list should only be traversed once.
For example if the list is 11 11 11 21 43 43 60 then you should convert the list to 11 21 43 60.

Input Specification:
a list sorted in non-decreasing order.
-1 denotes the end of input. -1 is not to be processed.
The list is not empty.
(输入是一个非降序列表,每个整数之间以空格隔开,输入-1表示输入结束。-1不需要处理。列表中至少有1个元素)
Output Specification:
The list without duplicate nodes.(输出去掉重复元素之后的列表,每个整数后加一个空格)

Sample Input 1:
11 11 11 21 43 43 60 -1
Sample Output 1:
11 21 43 60
Sample Input 2:
1 1 1 2 3 3 9 -1
Sample Output 2:
1 2 3 9
Sample Input 3:
9 9 9 9 9 9 9 9 -1
Sample Output 3:
9

// #include <stdio.h>

// int arr[100009];
// int main(){
//     int cnt=0,x;
//     while(scanf("%d",&x) && x!=-1){
//         arr[cnt++]=x;
//     }
//     printf("%d ",arr[0]);
//     for(int i=1;i<cnt;i++){
//         if(arr[i]!=arr[i-1]) 
//             printf("%d ",arr[i]);
//     }
//     return 0;
// }


#include <stdio.h>

int main(){
    int cur,pre=-1;
    while(1){
        scanf("%d",&cur);
        if(cur==-1) break;
        if(cur!=pre){
            printf("%d ",cur);
            pre=cur;
        }
    }
    return 0;
}

7-66 输入金额输出各种面额数量(数组、浮点数精度)

从键盘输入一指定金额(以元为单位,如345.78),然后显示支付该金额的各种面额人民币数量,要求显示100元、50元、10元、5元、2元、1元、5角、1角、5分、1分各多少张。(输出面额最大值)
比如:345.78=100∗3+10∗4+5∗1+0.5∗1+0.1∗2+0.05∗1+0.01∗3

输入格式:
输入指定金额以元为单位,如:345.78
输出格式:
输出各面额组成的算式:
金额输出小数点后两位,某面额数为0则不输出该面额,等号后第一个面额前无“+”,输出完成后换行。
如:345.78=100∗3+10∗4+5∗1+0.5∗1+0.1∗2+0.05∗1+0.01∗3
如:23.27=10∗2+2∗1+1∗1+0.1∗2+0.05∗1+0.01∗2
如果金额小于等于零则输出“输入有误”。

输入样例1:
在这里给出一组输入。例如:
345.78
输出样例1:
在这里给出相应的输出。例如:
345.78=1003+104+51+0.51+0.12+0.051+0.013
输入样例2:
在这里给出一组输入。例如:
23.27
输出样例2:
在这里给出相应的输出。例如:
23.27=10
2+21+11+0.12+0.051+0.01*2
金融计算:涉及金额和货币运算时,为了确保准确性,避免浮点数精度误差导致的错误; 金额显示:当金额需要显示到小数点后两位(如元的两位小数),确保输出格式一致;货币处理:在处理交易、账单、税务等需要精确金额的应用中,使用四舍五入来避免因浮点数精度问题引发的误差。
浮点数在内存中的存储是不精确的,有时候可能会加0.000001

#include <stdio.h>

double amounts[]={100,50,10,5,2,1,0.5,0.1,0.05,0.01};
int counts[10];
int main(){
    double m;scanf("%lf",&m);
    if(m<=0){
        printf("输入有误");
        return 0;
    } 
    double y=m;
    // 方法一
    // for(int i=0;i<10;i++){
    //     counts[i]=m/amounts[i];
    //     m=m-counts[i]*amounts[i];
    //     // 浮点数精度处理
    //     m=(int)(m*100+0.5) / 100.0;
    // }
    // 方法二
    for(int i=0;i<10;i++){
        counts[i]=(m+0.000001)/amounts[i];
        m=m-counts[i]*amounts[i];
    }
    printf("%.2f=",y);
    int first=1;
    for(int i=0;i<10;i++){
        if(counts[i]>0){
            if(!first) printf("+");
            first=0;
            if(amounts[i]>=1) // 100 10 5
                // printf("%.0f*%d",amounts[i],counts[i]);
                printf("%d*%d",(int)amounts[i],counts[i]);
            else if(amounts[i]>=0.1) // 0.5 0.1
                printf("%.1f*%d",amounts[i],counts[i]);
            else // 0.05 0.01
                printf("%.2f*%d",amounts[i],counts[i]);
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值