PTA 2022秋季C语言专题实验06

目录

7-1 二分法求方程的近似根

7-2 哥德巴赫猜想

7-3 求整数序列中出现次数最多的数

7-4 6174问题

7-5 数组中插入一个数

7-6 数组元素的删除

7-7 删除重复元素

7-8 逐行排序

7-9 统计单词个数(指针实现统计单词个数)


7-1 二分法求方程的近似根

任务描述

二分法求方程近似根的基本思想是:

(1)设定初始有根区间[a,b];

(2)找到区间的中点x=(a+b)/2;

(3)如果|f(x)|< ε,则认为该点x就是方程的近似根(ε是一个极小值);

(4)如果f(x)与f(a)同号,则把x赋值给a;否则把x赋值给b;

(5)转向步骤(2)开始下一次迭代。

已知函数 f(x)=x5−2x4+x2−3在区间[0,2]内与x轴肯定有交点,即方程f(x)=0有根,

请编程用二分法求出方程在区间[0,2]内的一个近似根。算法中的ε取值由输入得到。

输入格式:

一个很小的实数,代表ε。

输出格式:

一个近似根,保留8位小数。

输入样例:

0.001

输出样例:

1.94519043

输入样例:

0.00000001

输出样例:

1.94524686

 代码:

#include<stdio.h>
#include<math.h>
double f(double x)
{
    double y = pow(x,5)-2*pow(x,4)+pow(x,2)-3;//pow()次方函数
    return y;
}
int main()
{
    double s,x;
    scanf("%lf",&s);
    double a = 0.0,b = 2.0;
    while(s > 0)
    {
        x = (a+b) / 2;
        if(fabs(f(x)) < s)//fabs()求浮点型绝对值
        {
            printf("%.8f",x);
            break;
        }
        else
        {
            if(f(x)*f(a) > 0)
                a = x;
            else b = x;
        }
    }
    return 0;
}

7-2 哥德巴赫猜想

“这是我和其他选手比谁过题过得更快的游戏”

对于任何大于或等于4的偶数n,存在至少一对素数p1和p2,使得n = p1 + p2
没有人确定这个猜想是否真的成立。然而,对于给定的偶数,可以找到这样的一对素数(如果有的话)。这里的问题是编写一个程序,打印出满足给定偶数的猜想条件的所有素数对数。

一个偶数序列作为输入。可以有很多这样的数字。对应于每个数字,程序应输出上述对的数量。请注意,我们只统计不同的数对,因此不应将(p1,p2)和(p2,p1)分别计为两对不同的对。

输入格式:

在每个输入行中给出一个整数。你可以假定每个整数是偶数,并且大于或等于4且小于2的15次方。输入的结尾用数字0表示。

输出格式:

每个输出行应该包含一个整数。输出中不应出现其他字符。

输入样例:

在这里给出一组输入。例如:

6
10
12
0

输出样例:

在这里给出相应的输出。例如:

1
2
1

代码: 

#include <stdio.h>
 
int main()
{
    int n, i, j;
    scanf("%d",&n);
    while(n != 0)
    {
        int a[n];
        for(i = 0; i < n; i++)      //先将数组所有元素赋值为1
        {
            a[i] = 1;
        }
        for(i = 2; i <= n/2; i++)   //通过筛选法求素数将不是素数下表的元素改为0
        {
            for(j = i; j*i < n; j++)
            {
                a[i*j] = 0;
            }
        }
        int count = 0;                   //计数每当两个素数相加等于n时,count+1
        for(i = 2; i <= n/2; i++)//1不是素数,从2开始
        {
            if(a[i] == 1 && a[n-i] == 1)
                count++;
        }
        printf("%d\n",count);
        scanf("%d", &n);
    }
 
}

7-3 求整数序列中出现次数最多的数

本题要求统计一个整型序列中出现次数最多的整数及其出现次数。

输入格式:

输入在一行中给出序列中整数个数N(0<N≤1000),以及N个整数。数字间以空格分隔。

输出格式:

在一行中输出出现次数最多的整数及其出现次数,数字间以空格分隔。题目保证这样的数字是唯一的。

输入样例:

10 3 2 -1 5 3 4 3 0 3 2

输出样例:

3 4

代码: 

#include<stdio.h>
int main()
{
    int num,n,i,j;
    scanf("%d",&num);//num整数个数
    int a[1001];
    for(i=0;i<num;i++)//存放输入的数
        scanf("%d",&a[i]);
    int count=0,value=0;//count存放出现次数最多的整数的次数,value存放出现次数最多的整数
    for(i=0;i<num;i++)
    {
        int c=0;
        for(j=i;j<num;j++)
        {
            if(a[i]==a[j])
                c++;//计算这个数出现的次数
        }
        if(c>count)//若这个数出现的次数不是目前最多的
            {
                count=c;
                value=a[i];
            }
    }
    printf("%d %d",value,count);
    return 0;
}

7-4 6174问题

任务描述

著名的“6174黑洞”问题描述如下:
对于任意一个各位数字不全相同的4位正整数n,对n进行以下变换:把n所有的数字从大到小排序后得到整数a,
所有的数字从小到大排列后得到整数b,然后把a-b做为新的4位整数n,然后重复以上变换操作,直到得到6174,
然后便进入7641-1476=6174的陷阱(黑洞)。
(所有计算过程中如果得到4位以下的数,可以在整数左侧补0补足4位)

例如,从9998出发,依次可以得到
(第1次变换)9998-8999=0999
(第2次变换)9990-0999=8991
(第3次变换)9981-1899=8082
(第4次变换)8820-0288=8532
(第5次变换)8532-2358=6174
(以后进入黑洞,出不来)6174-6174=6174
经过5次变换后,得到6174。

再例如,从1234出发,依次可以得到
(第1次变换)4321-1234=3087、
(第2次变换)8730-0378=8352、
(第3次变换)8532-2358=6174、
(以后进入黑洞,出不来)6174-6174=6174
经过3次变换后,得到6174。

也就是说,对于任意一个各位数字不全相同的4位正整数n经过若干步骤计算,最终会是到6174,并陷入6174
的轮回!这就是数学上著名的6174黑洞问题。

现在要你写一个程序来输出一个四位数要经过多少次这样的变换能得到6174,比如
对于输入1234,应该输出3,对于输入9998,应该输出5。

输入格式:

第一个整数k,代表有k组测试数据。接下来是k个4位整数(保证4位数字不全相同)。

输出格式:

每行输出一个整数,代表一组数据的结果。

输入样例:

2 1234 9998

输出样例:

3
5

 代码: 

#include<stdio.h>
#include<math.h>
int main()
{
    int n=0,i,j,k,t=0,temp;
    scanf("%d",&k);//k组测试数据
    int c[4];
    for(int l=0;l<k;l++)
    {
        scanf("%d",&n);
        while(n!=6174)
        {
            for(i=0;i<4;i++)
        {
           c[0]=n%10;//c数组存放个位,十位,百位,千位
           c[1]=n/10%10;
           c[2]=n/100%10;
           c[3]=n/1000%10;
        }
        for(i=0;i<3;i++)//选择排序:从小到大
        {
            for(j=i+1;j<4;j++)//循环找出每一次遍历的最小值移到最前面
                if(c[i]>c[j])//c[i]>c[j],交换值
                {
                    temp=c[i];
                    c[i]=c[j];
                    c[j]=temp;
                }
        }
        int a,b,result;
        a=c[3]*1000+c[2]*100+c[1]*10+c[0];
        b=c[0]*1000+c[1]*100+c[2]*10+c[3];
        result=a-b;
        t++;//变换次数
        n=result;//n:新的4位整数
        }
        printf("%d\n",t);
        t=0;//次数归零,计下一个数
    }
    return 0;
}

7-5 数组中插入一个数

在一个已按升序排列的数组中插入一个数,插入后,数组元素仍按升序排列,已知升序数组{1, 2, 4, 6, 8, 9, 12, 15, 149, 156 }。

输入格式:

直接输入一个整数,没有其它任何附加字符。。

输出格式:

输出插入元素后的升序数列,每个数输出占5列。

输入样例:

5

输出样例:

    1    2    4    5    6    8    9   12   15  149  156

代码: 

#include<stdio.h>
int main() 
{
    int i, j, x;
    int a[11] = { 1,2,4,6,8,9,12,15,149,156 };
    scanf("%d", &x);
    for (i = 0; i < 10; i++)
        if (x < a[i])//找到x需要插入的位置下标
            break;
    for (j = 10; j > i; j--)//将后面的数往后移,给x腾出空间
        a[j] = a[j - 1];
    a[j] = x;//将x插入
    for (i = 0; i < 11; i++)
        printf("%5d", a[i]);
    printf("\n");
    return 0;
}

7-6 数组元素的删除

完成数组元素的移动功能:假设数组有n个元素,输入一个数x,把数组的第x个位置的元素删除了,后面的元素依次前进一个位置。
重复若干次这样的删除,得到最后的结果。

输入格式:

第一行包括一个整数n(1<=n<=100),表示数组元素的个数。
第二行输入n个数组元素,均为整数,用空格隔开。
第三行输入一个数k(1<=k<=100),表示要进行k次删除。
接下来k行,每行一个数x,表示要删除第x个元素。

输出格式:

输出经过k次删除后的数组,每两个元素之间用空格隔开。

输入样例:

10
1 2 3 4 5 6 7 8 9 10
4
3
2
4
6

输出样例:

1 4 5 7 8 10

代码:  

#include<stdio.h>
int main()
{
    int n, k, x,i;
    scanf("%d",&n);
    int a[n];
    for(i=0;i<n;i++)
    {
        scanf("%d",&a[i]);
    }
    scanf("%d",&k);
    for(int j=0;j<k;j++)
    {
        scanf("%d",&x);
        for(i=x;i<n;i++)
            a[i-1]=a[i];//将后面的数往前移1位
        a[n--];
    }
    for(i=0;i<n-1;i++)
    {
        printf("%d ",a[i]);
    }
    printf("%d\n",a[n]);//最后一个数没有空格
    return 0;
}

7-7 删除重复元素

对于给定的数列,要求把其中的重复元素删去再从小到大输出。

输入格式:

首先输入一个正整数T,表示测试数据的组数,然后是T组测试数据。每组测试数据先输入一个整数n(1≤n≤100),再输入n个整数。

输出格式:

对于每组测试,从小到大输出删除重复元素之后的结果,每两个数据之间留一个空格。

输入样例:

1
10 1 2 2 2 3 3 1 5 4 5

输出样例:

1 2 3 4 5

代码:  

#include<stdio.h>
int main()
{
	int T,i,j,k,a[100],n,t;
	scanf("%d",&T);
	for(i=1;i<=T;i++)
    {
	    scanf("%d",&n);
	for(j=0;j<n;j++)
		scanf("%d",&a[j]);//输入数据 
	for(j=0;j<n;j++)
     {
	    for(k=j+1;k<n;k++)
	     {
		    if(a[k]==a[j])       //从数组第一位开始与后面的数进行比较,判断重复 
		    {
		    	for(int c=k;c<n;c++)//有重复就将该数移除
		    	{
				   a[c]=a[c+1];
		     	}
		    	   n--;//重复的元素已经被删除了,所以总数-1
		    	   k--;//被删除的元素的原位置填入了后一个元素,如果不执行k--,当进入下一次循
                       //环时会执行k++,即跳过了新元素
			}
	     }
	 }
	 //采用冒泡排序
	for(j=0; j<n-1; j++)
	{
        //每轮比较前n-1-j个,也就是说已经排序好的最后j个不用比较
        for(int k=0;k<n-1-j;k++)
		{
			int temp;
            if(a[k]>a[k+1])
			{
                temp=a[k];
                a[k]=a[k+1];
                a[k+1]=temp;
            }
        }
    }
    for(j=0;j<n-1;j++)//输出前n-1个
         printf("%d ",a[j]);
    printf("%d",a[n-1]);//输出最后一个
    printf("\n");
    }
}

7-8 逐行排序

给你一个n阶方阵,请你把每行数据按数据从小到大排序并输出。

输入格式:

输入数据首先包含一个整数T,表示测试实例的个数,然后是T组测试数据。
每组测试数据的第一行输入1个整数n(1<n<20),接下来输入n行数据,每行n个整数。

输出格式:

对于每组测试,输出排好序后的结果。每行中各数据之间留一个空格。

输入样例:

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

输出样例:

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

代码:  

#include <stdio.h>
int main()
{
    int T, n, i, j, k;
    scanf("%d",&T);                     //输入测试组数
    for(i = 1; i <= T; i++)             //循环t次
    {
        scanf("%d",&n);                 //输入二维数组的行列
        int a[n][n];                    //定义二维数组
        for(k = 0; k < n; k++)          //给二位数组输入元素
            for(j = 0; j < n; j++)      
                scanf("%d",&a[k][j]);
    //采用冒泡排序
	for(int h=0; h<n; h++)             //行循环
	{
        for(int c=0; c<n-1; c++)       //每行需要排序的次数
        {
            //每轮比较前n-1-c个,也就是说已经排序好的最后c个不用比较
          for(int l=0;l<n-1-c;l++)       //每行需要交换的次数
		  {
			int temp;
            if(a[h][l]>a[h][l+1])       //只排序每一行的大小
			{
                temp=a[h][l];
                a[h][l]=a[h][l+1];
                a[h][l+1]=temp;
            }
          }
        }
        
    }
        for(k = 0; k < n; k++)           //按规定输出
        {
            for(j = 0; j < n; j++)
            {
                if(j == 0)               //先输出第一个无空格
                {
                    printf("%d",a);
                }
                else
                {
                    printf(" %d",a[k][j]);
                }
            }
            printf("\n");
        }
    }
}

7-9 统计单词个数(指针实现统计单词个数)

任务描述

在一行中输入一个英文句子(不超过100个字符),输出这个句子中单词的个数,单词之间以空格分隔,除空格外都认为是单词(包括符号)。

输入样例:

This     is    a    C    program.     <<<     =22=     ,,,     END

输出样例:

9

代码:  

#include <stdio.h>
int main(void) {
	char str[100], *p;    //定义字符数组和字符指针。
	int count = 0;    //计数多少个单词。
	gets(str);    //输入,获取字符串。
	for ( p = str; *p!=0; ) 
    {    //p指针指向字符串str,*p表示p指向'\0'是中断循环。
		if ( *p != ' ' ) 
        {    //检测到非空格,算一个单词。
			count++;
			while ( *p != ' ' && *p )	p++;    //移动指针跳过这个单词后的字母。
		} 
        else 
			p++;    //若检测到空格,移动指针。p++相当于str[i++]
	}
	printf("%d", count);
	return 0;
}

  • 5
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值