2022秋 | PTA编程训练(一)

目录

1.素数对猜想

2.数组元素循环右移问题

3.水仙花数

4.找出不是两个数组共有的元素

5.找鞍点

6.验证“哥德巴赫猜想”

7.黑洞数

8.装箱问题

9.IP地址转换

10.龟兔赛跑


1.素数对猜想

题目详情:

让我们定义dn​为:dn​=pn+1​−pn​,其中pi​是第i个素数。显然有d1​=1,且对于n>1有dn​是偶数。“素数对猜想”认为“存在无穷多对相邻且差为2的素数”。

现给定任意正整数N(<105),请计算不超过N的满足猜想的素数对的个数。

 输入格式:

输入在一行给出正整数N

 输出格式:

在一行中输出不超过N的满足猜想的素数对的个数。

 输入样例:

20

 输出样例:

4

代码长度限制                                                                                                                  16 KB

时间限制                                                                                                                        400 ms

内存限制                                                                                                                         64 MB

 代码及解析如下:

#include <stdio.h>
#define P 100000
int isprime(int ); //判断一个数是否为素数
int a[P];          //存放N以内的素数
int main(){
    int count=0;  //计数器,计算素数对的个数
    int i=0,j=0;  
    int N=0;
    scanf("%d",&N);
    for(i=0;i<=N;i++){
        if(isprime(i)){ //
            a[j++]=i;   //将N以内的素数放到数组里
        }
    }
    for(i=0;i<j;i++){
        if((a[i+1]-a[i])==2){  //如果满足素数对的条件
            count++;           //则计数器加一
        }
}
    printf("%d",count);
}
int isprime(int x){
    if(x<=1)return 0;
    for(int i=2;i*i<=x;i++){
        if(x%i==0){
            return 0;
        }
    }
    return 1;
}

2.数组元素循环右移问题

题目详情:

一个数组A中存有N(>0)个整数,在不允许使用另外数组的前提下,将每个整数循环向右移M(≥0)个位置,即将A中的数据由(A0​A1​⋯AN−1​)变换为(AN−M​⋯AN−1​A0​A1​⋯AN−M−1​)(最后M个数循环移至最前面的M个位置)。如果需要考虑程序移动数据的次数尽量少,要如何设计移动的方法?

输入格式:

每个输入包含一个测试用例,第1行输入N(1≤N≤100)和M(≥0);第2行输入N个整数,之间用空格分隔。

输出格式:

在一行中输出循环右移M位以后的整数序列,之间用空格分隔,序列结尾不能有多余空格。

 输入样例:

6 2
1 2 3 4 5 6

 输出样例:

5 6 1 2 3 4

 代码及解析如下:

#include <stdio.h>
#define P 100
int main(){
    int N=0,M=0;  //N数组元素个数,M循环右移次数
    scanf("%d %d",&N,&M);
    int a[P];
    int i=0;
    for(i=0;i<N;i++){
        scanf("%d",&a[i]);  //输入数组元素
    }
    for(i=0;i<M;i++){     //循环右移M次
        //先将最后一位数临时拷贝以下,防止被覆盖
        int temp=a[N-1];  
        int j;
        //再将每个数赋给它的后面一位,形成数组的一次右移
        //该操作要从后往前执行
        for(j=N-2;j>=0;j--){  
            a[j+1]=a[j];  
        }
        //上面的循环结束后,j=-1,+1后把临时拷贝的a[n-1]赋进去,完成该次循环右移
        a[j+1]=temp;  
    }
    for(i=0;i<N;i++){
        printf("%d",a[i]);
        if(i<N-1)printf(" ");
    }
    return 0;
}

3.水仙花数

题目详情:

水仙花数是指一个N位正整数(N≥3),它的每个位上的数字的N次幂之和等于它本身。例如:153=13+53+33。 本题要求编写程序,计算所有N位水仙花数。

输入格式:

输入在一行中给出一个正整数N(3≤N≤7)。

输出格式:

按递增顺序输出所有N位水仙花数,每个数字占一行。

输入样例:

3

输出样例:

153
370
371
407

代码及解析如下:

#include <stdio.h>
int p(int ,int );  //定义函数计算N次幂
int main(){
    int N;    //输入N位数
    scanf("%d",&N);
    int mask=1;
    //定义mask变量,可以算出N位数的起始区间
    for(int i=0;i<N-1;i++){     
        mask*=10;                  
    }
    int sum;
    //计算出N位数的起始区间,比如3位数的起始区间为100-999
    for(int j=mask;j<mask*10;j++){
        int m=j;     //某一个N位数
        sum=0;
        while(m){       
            int temp=m%10;   //将每个位上的数字取出来  
            sum+=p(temp,N);  //计算每个位上的N次幂之和
            m/=10;          
        }
        if(j==sum)printf("%d\n",j);
    }
    return 0;
}
int p(int x,int y){  //计算N次幂
    int i=1,j=1;
    for(i=0;i<y;i++){
        j*=x;
    }
    return j;
}

4.找出不是两个数组共有的元素

题目详情:

给定两个整型数组,本题要求找出不是两者共有的元素。

输入格式:

输入分别在两行中给出两个整型数组,每行先给出正整数N(≤20),随后是N个整数,其间以空格分隔。

输出格式:

在一行中按照数字给出的顺序输出不是两数组共有的元素,数字间以空格分隔,但行末不得有多余的空格。题目保证至少存在一个这样的数字。同一数字不重复输出。

输入样例:

10 3 -5 2 8 0 3 5 -15 9 100
11 6 4 8 2 6 -5 9 0 100 8 1

输出样例:

3 5 -15 6 4 1

代码及解析如下:

#include <stdio.h>
#define P 100
int main(){
    int a[P],b[P];
    int N,M,i,j;
    scanf("%d",&N);
    for(i=0;i<N;i++){
        scanf("%d",&a[i]);  //输入长度为N的数组a
    }
    scanf("%d",&M);
    for(i=0;i<M;i++){
        scanf("%d",&b[i]);  //输入长度为M的数组b
    }
    int count=0;
    int c[P];         //定义一个新数组存放两数组中相同的数
        for(i=0;i<N;i++){  //先拿着数组a中的每个元素去比较数组b中的每个元素
            for(j=0;j<M;j++){
                if(a[i]==b[j])  //如果有相同的数,跳出该层循环
                    break;
            }
            if(j==M)c[count++]=a[i];  //j=M表示遍历整个数组b都没有相同的数
        }
    for(i=0;i<M;i++){
        for(j=0;j<N;j++){
            if(b[i]==a[j])break;  
        }if(j==N)c[count++]=b[i];  //拿着数组b中的每个数去比较数组a中的数,类似上述步骤   
    }
    printf("%d",c[0]);
    for(i=1;i<count;i++){
        for(j=0;j<i;j++){
            if(c[i]==c[j])break;   //判断数组c中有无重复的数
        }
        if(j==i)printf(" %d",c[i]);
    }
    return 0;
}

5.找鞍点

题目详情:

一个矩阵元素的“鞍点”是指该位置上的元素值在该行上最大、在该列上最小。

本题要求编写程序,求一个给定的n阶方阵的鞍点。

输入格式:

输入第一行给出一个正整数n(1≤n≤6)。随后n行,每行给出n个整数,其间以空格分隔。

 输出格式:

输出在一行中按照“行下标 列下标”(下标从0开始)的格式输出鞍点的位置。如果鞍点不存在,则输出“NONE”。题目保证给出的矩阵至多存在一个鞍点。

输入样例:

4
1 7 4 1
4 8 3 6
1 6 1 2
0 7 8 9

 输出样例 :

2 1

 代码及解析如下:

#include <stdio.h>
#define P 100
int main(){
    int a[P][P];
    int n;
    scanf("%d",&n);
    int i,j;
    for(i=0;i<n;i++){
        for(j=0;j<n;j++){
            scanf("%d",&a[i][j]);  //输入n*n的矩阵
        }
    }
    int b=0,k;
    int temp=0;
    for(i=0;i<n;i++){
        for(j=0;j<n;j++){
            if(a[i][j]>=a[i][b]){  //先找到每行上最大的数a[i][b]
                b=j;
            }
        }
        temp=1;
        for(k=0;k<n;k++){
            if(a[k][b]<a[i][b]){  //在该数所在的列上逐行向下找有没有小于a[i][b]的数
                temp=0;           //如果有,则标记0,说明a[i][b]不是要找的数
                break;                      
            }                     
        }
        if(temp)break;  //如果没有,说明数a[i][b]在所在列上是最小的
    }
    if(temp)printf("%d %d",i,b);   //打印其所在位置i,b
    else printf("NONE");
    return 0;
}

6.验证“哥德巴赫猜想”

题目详情:

数学领域著名的“哥德巴赫猜想”的大致意思是:任何一个大于2的偶数总能表示为两个素数之和。比如:24=5+19,其中5和19都是素数。本实验的任务是设计一个程序,验证20亿以内的偶数都可以分解成两个素数之和。

输入格式:

输入在一行中给出一个(2, 2 000 000 000]范围内的偶数N。

输出格式:

在一行中按照格式“N = p + q”输出N的素数分解,其中p ≤ q均为素数。又因为这样的分解不唯一(例如24还可以分解为7+17),要求必须输出所有解中p最小的解。

输入样例:

24

输出样例:

24 = 5 + 19

代码及解析如下:

#include <stdio.h>
int p(int );
int main(){
    long long n;  //题目说20亿以内,所以整数要定义的足够大
    scanf("%d",&n);
    int i;
    for(i=2;i<n;i++){
        if(p(i)&&p(n-i)){  //满足:1.两数相加为n 2.两数都是素数
            printf("%d = %d + %d",n,i,n-i);
            break;
        }
    }
    return 0;
}
int p(int x){   //判断是否为素数
    if(x<=1)return 0;
    for(int i=2;i*i<=x;i++){
        if(x%i==0)
            return 0;
    }
    return 1;
}

 补:long/int型的范围 -2147483648(-2^{31})~~~2147483647(2^{31})

        long long型的范围-9223372036854775808(-2^{63})~~~9223372036854775807(2^{63})

7.黑洞数

题目详情:

黑洞数也称为陷阱数,又称“Kaprekar问题”,是一类具有奇特转换特性的数。

任何一个各位数字不全相同的三位数,经有限次“重排求差”操作,总会得到495。最后所得的495即为三位黑洞数。所谓“重排求差”操作即组成该数的数字重排后的最大数减去重排后的最小数。(6174为四位黑洞数。)

例如,对三位数207:

  • 第1次重排求差得:720 - 27 = 693;
  • 第2次重排求差得:963 - 369 = 594;
  • 第3次重排求差得:954 - 459 = 495;

以后会停留在495这一黑洞数。如果三位数的3个数字全相同,一次转换后即为0。

任意输入一个三位数,编程给出重排求差的过程。

输入格式:

输入在一行中给出一个三位数。

输出格式:

按照以下格式输出重排求差的过程:

序号: 数字重排后的最大数 - 重排后的最小数 = 差值

输入样例:

123

 输出格式:

1: 321 - 123 = 198
2: 981 - 189 = 792
3: 972 - 279 = 693
4: 963 - 369 = 594
5: 954 - 459 = 495

 代码及解析如下:

#include <stdio.h>
int p(int );
int q(int );
int main(){
    int n,p=1;
    scanf("%d",&n); //输入某一个三位数数
    int n1,n2;
    while(1){
        int i,j,k,t;
        i=n%10;  
        j=n/10%10;
        k=n/100;  //把该三位数的各位数分别取出来
        if(i<j){ 
            t=i;
            i=j;
            j=t;
        }            //
        if(i<k){     //  比较各位数上的大小
            t=i;     //
            i=k;
            k=t;
        }
        if(j<k){
            t=j;
            j=k;
            k=t;
        }
        n1=100*k+10*j+i;  //重排后最小的数
        n2=100*i+10*j+k;  //重排后最大的数
        n=n2-n1;          
        printf("%d: %d - %d = %d\n",p,n2,n1,n);
        p++;
        if(n==495)break;  //判断两数相减是不是黑洞数
    }
    return 0;
}

8.装箱问题

题目详情:

假设有N项物品,大小分别为s1​、s2​、…、si​、…、sN​,其中si​为满足1≤si​≤100的整数。要把这些物品装入到容量为100的一批箱子(序号1-N)中。装箱方法是:对每项物品, 顺序扫描箱子,把该物品放入足以能够容下它的第一个箱子中。请写一个程序模拟这种装箱过程,并输出每个物品所在的箱子序号,以及放置全部物品所需的箱子数目。

输入格式:

输入第一行给出物品个数N(≤1000);第二行给出N个正整数si​(1≤si​≤100,表示第i项物品的大小)。

输出格式:

按照输入顺序输出每个物品的大小及其所在的箱子序号,每个物品占1行,最后一行输出所需的箱子数目。

输入样例:

8
60 70 80 90 30 40 10 20

输出样例:

60 1
70 2
80 3
90 4
30 1
40 5
10 1
20 2
5

 代码及解析如下:

#include <stdio.h>
#define P 1001
int main(){
    int n;
    scanf("%d",&n);  //输入物品个数
    int a[P],b[P];   //数组a用力存放物品的大小,数组b用来表示每个箱子存了多大的东西
    int i,j;
    for(i=0;i<n;i++){
        scanf("%d ",&a[i]);  //输入每个物品的大小
        b[i]=0;              //刚开始箱子什么都每存,初始化位0
    }
    int max=0;
    for(i=0;i<n;i++){            //每一个物品,都从1号箱子开始遍历
        for(j=1;j<=n;j++){       //
            if(a[i]+b[j]<=100){  //判断该物品能否放入当前的箱子
                b[j]+=a[i];      //
          
            printf("%d %d\n",a[i],j);
            if(max<j){
                max=j;          //计算用了多少箱子
            }
                break;
            }
        }
        
    }
    printf("%d",max);
    return 0;
}

9.IP地址转换

题目详情:

一个IP地址是用四个字节(每个字节8个位)的二进制码组成。请将32位二进制码表示的IP地址转换为十进制格式表示的IP地址输出。

输入格式:

输入在一行中给出32位二进制字符串。

输出格式:

在一行中输出十进制格式的IP地址,其由4个十进制数组成(分别对应4个8位的二进制数),中间用“.”分隔开。

输入样例:

11001100100101000001010101110010

输出样例:

204.148.21.114

代码及解析如下:

//题目中说是32位IP地址,远远超出整形变量的取值范围
//所以不能定义整型变量来做,应考虑数组

#include <stdio.h>
int f(char *);
int main(){
    char a[4][8];   //IP地址分为四节,每节8个二进制数,所以定义一个4*8的二维数组
    
    for(int i=0;i<4;i++){
        scanf("%s",a[i]);  //输入二维数组
    }
    int n1=f(a[0]);
    int n2=f(a[1]);
    int n3=f(a[2]);
    int n4=f(a[3]);
    printf("%d.%d.%d.%d",n1,n2,n3,n4);
    return 0;
}
int f(char *b){  //二进制转十进制
    int sum=0;                    
    int n=128;         //2的7次方
    for(int i=0;i<8;i++){
        sum+=(b[i]-'0')*n;  //b[i]是字符型,减‘0’为当前的整形二进制
        n/=2;                //将该位上的二进制数从高到低乘上该位的位权
    }                        //得到的就是十进制数
    return sum;
    
}

10.龟兔赛跑

题目详情:

乌龟与兔子进行赛跑,跑场是一个矩型跑道,跑道边可以随地进行休息。乌龟每分钟可以前进3米,兔子每分钟前进9米;兔子嫌乌龟跑得慢,觉得肯定能跑赢乌龟,于是,每跑10分钟回头看一下乌龟,若发现自己超过乌龟,就在路边休息,每次休息30分钟,否则继续跑10分钟;而乌龟非常努力,一直跑,不休息。假定乌龟与兔子在同一起点同一时刻开始起跑,请问T分钟后乌龟和兔子谁跑得快?

输入格式:

输入在一行中给出比赛时间T(分钟)。 

输出格式:

在一行中输出比赛的结果:乌龟赢输出@_@,兔子赢输出^_^,平局则输出-_-;后跟1空格,再输出胜利者跑完的距离。

输入样例:

242

输出样例:

@_@ 726

代码及解析如下:

#include <stdio.h>
int main(){
    int t,n=0,m=0;  //n乌龟前进米数,m兔子前进米数
    scanf("%d",&t);
    int i;
    int count=0;    //计算兔子休息的时间
    for(i=0;i<t;i++){
        n+=3;       //乌龟每分钟跑3米
        if(i%10==0&&m>n&&count<30){  //如果兔子跑了10分钟且超过乌龟且兔子不处于休息状态
            count++;                //兔子开始休息
        }
        else if(count==0||count==30){  //如果兔子一直在跑或兔子刚休息结束
            m+=9;
            count=0;      //休息时间从0开始计数
        }
        else count++;    //兔子处于休息状态
    }

    if(n>m){
        printf("@_@ %d",n);
    }
    else if(m>n){
        printf("^_^ %d",m);
    }
    else{
        printf("-_- %d",m);
            }
    return 0;
}

注:     本栏目所有的题目均来自于学校程序设计课程的平时作业,如果对您有帮助的话,请点赞加关注,有任何不理解的地方也可以在评论区中留言或者私信我哦!

  • 11
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

殿下p

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值