PAT(乙) 1005~1007(附图解)

目录

1005.继续(3n+1)猜想

1006.换个格式输出整数

1007.素数对猜想​


1005.继续(3n+1)猜想

(题干,我做的时候有点让人头大)

总结一下就四点 :

(前两点是:1001中的给定的前提条件这里解释一下;后两点是这道题新添加的设定)

1. 有一个数 x ,如果 x 是偶数则:x = x/2 ;x 是奇数则:x = (x*3+1)/2 ;

2. 最终 x 会在经历了多次计算后 ,变成 1 ;

3. 定义覆盖: x 在多次计算时会成为的多个不同的值 ,而这些值则称为被 x 所覆盖的值。

例如 x = 3 过程为:x = 3 > 8 > 4 > 2 > 1 (而这个过程中  8 ,4,2 就是被 x 所覆盖的值)

(注意:1不算)

4. 现给一个数列:从大到小输出这个数列中不被覆盖的数 。

思路:1.遍历数列,包含两部分循环(一是对数列的遍历,二是每个数都有一个变为 1 的过程。)

          2.对被覆盖的数进行标记 。

          3.依据标记 ,输出未被覆盖的数 。

实现细节:

1. 双层循环:

    每个数都有被其他数覆盖的可能 ,不分先后顺序。

    因此每个数,要遍历一下整个数组,检查有没有被他覆盖的值 ,所以要进行两层循环 ,

    外层是要进行检查的数,内层是被检查的数,(并且每次检查是检查整个数组)。

2. 检查方法:就是模拟一遍检查数逐渐变为 1 的过程,如果过程中被检查数 等于 检查数 ,

                    就将其标记下来。

3. 标记方法:类似于哈希表的映射思想,建立一个新数组,存放原数组的数据,

                    检查过程中如果该数据被覆盖,则在新数组中将对应位置置为 0 ,

                    以此类推,最终保留在新数组中的数就是,没有被覆盖的数 。

4. 别忘记对检查完的新数组进行排序,因为给定的数列没说是升序。

5. 这道题的输出要求是,最后数据的打印不带空格 。

void Verify(int* Tem, int test,int kem)  //检查函数
{
    for (; test != 1;)
    {
        if (0 == test % 2)
            test /= 2;
        else
            test = (test * 3 + 1) / 2;
        if (test == kem)                 //判断是否被覆盖
            Tem[kem] = 0;                //如果被覆盖,就将这个位置赋 0 
    }
}
void sqor(int* arr,int number)           //冒泡排序
{
    number = 101;
    for (int i = 0; i < number - 1; i++) 
    {
        for (int j = 0; j < number - i - 1; j++)
        {
            if (arr[j] < arr[j + 1])
            {
                int tem = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = tem;
            }
        }
    }
}

#include<stdio.h>
int main()
{
    int arr[100] = { 0 };
    int Tem[101] = { 0 };                       //这里新数组大小101
    int number = 0;                             //因为数据可能为100
    scanf("%d", &number);
    for (int i = 0; i < number; i++)            //读取数据
    {
        scanf("%d", arr + i);
        Tem[arr[i]] = arr[i];                   //将数据储存到新数组的对应位置
    }
    for (int i = 0; i < number; i++)            //每个数据进行检查
    {
        for (int I = 0; I < number; I++)        //检查整个数组
        {
            if (Tem[arr[I]]&&arr[i]!=arr[I])    //如果被覆盖,就不需要二次检查
            {                                   //如果没被覆盖,就等待二次检查
                Verify(Tem, arr[i], arr[I]);
            }
        }
    }
    sqor(Tem,number);                           //检查完排序
    for (int i = 0; Tem[i]; i++)
    {
        printf("%d", Tem[i]);
        if (Tem[i + 1])                         //判断是否为最后的数据
            printf(" ");                        //打印空格
    }
}

1006.换个格式输出整数

 思路:B : 百位是几就打印几个B 

           S : 十位是几就打印几个S 

      个位 :个位是 X 就打印 123……X

实现细节:就把 百位,十位,个位的只保存下来,再依次打印即可。

#include<stdio.h>
int main()
{
    int data = 0;
    scanf("%d", &data);
    int GW = data % 10;            //保存个位
    int BW = data / 100;           //保存百位
    int SW = (data/10)%10;         //保存十位
    for (int i = 0; i < BW; i++)
        printf("B");
    for (int i = 0; i < SW; i++)
        printf("S");
    for (int i = 1; i <= GW; i++)
        printf("%d", i);
}

1007.素数对猜想

 题干梗概:就是给定一个数N,在2~N 中遍历其中的所有素数,其中如果两个素数相减为 2 

                 则称这两个数为一个素数对 。

思路:先找到2~N中的素数,在判断前后两个素数相减是否为2

实现细节:1. 判断素数要用到 sort()函数

                  (这个函数会返回传入数据的开方数,返回类型double)

 运行sort()如下:

#include<stdio.h>                //测试一下sqrt()函数
int main()
{
    for (int i = 0; i < 100; i++)
    {
        printf("传入:%d - 返回:%lf\n",i, sqrt(i));
    }
}

                                   

 因为一个数的因数除了1 和他本身 之外,其他的公因数必然分布在 他的开方数 的两侧 。

例如:

所以判定的是候只需要判定他开方数前有没有因数就可以了,如果开方数前有因数,则他开方数后也一定有因数,反之,则没有 。(注:开方数也需要判断是否为因数)

#include<stdio.h>

int Verify(int i)
{
    for (int I = 2; I < sqrt(i); I++)       //判断开方数前一半的数
    {
        if (0 == i % I)
            return 0;
    }
    return 1;
}

int main()
{
    int N = 0;
    scanf("%d", &N);
    int number = 0;                        //素数对个数
    int tem = 2;                           //记录前一个素数
    for (int i = 2; i <= N; i++)
    {
        if (Verify(i))                     //判断是否是素数
        {
            if (2 == (i - tem))            //判断前后素数相减是否为 2
            {
                number++;                  //统计素数对个数
            }
            tem = i;                       //记录前一个素数
        }
    }
    printf("%d", number);
    return 0;
}

非常感谢,各位大佬看到这里,有写的不对或不足的地方,请指出,我会虚心接受滴  。

最后的栓Q ! ! !

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值