2024蓝桥杯——宝石问题

先展示题目

声明

以下代码仅是我的个人看法,在自己考试过程中的优化版,本人考试就踩了很多坑,我会—一列举出来。代码可能很多,但是总体时间复杂度不高只有0(N²)

函数里面的动态数组我没有写开辟判断和free,这里我忽略掉了。

正文

先直接抛出最后的代码:

 

我也觉得太长了,大家可以当做知识点的掌握来看吧。

从数据中取出n个数的问题-->可以拓展到取出所有子集问题

先讲子集问题

这个问题我们可以用三个for循环来做,但是时间复杂度太高了。所以我们有以下的方法。

一个数取不取就有两种情况。我们可以用0或1来表示。那么我们就可以用二进制来表示我们的取或不取,用每位二进制的位置来对于每个元素。

例如:有1 2 两个数字。我们就可以用两位二进制来表示:00 01 10 11分别表示 不取任何数 取2 取1 都取。一共有2^2次方中情况

那么我们推广到n,就有2^n种。

我们来尝试写一下代码。

直接用二进制

完全没问题。

用数组模拟二进制

这里有一个问题不知道大家看到没:2^n 容易溢出。因此我们可以用数组来模拟二进制的自增。

自增问题涉及到进一问题,所以我们需要运用到递归,递归的判断终止条件就是n+1位由0变成1。

所以我们需要开辟n+1长度的数组nums。

用类似递归来实现
用循环(最优解)

这里几个continue和return一定要有,不然逻辑就错了

这样的话我们就可以遍历任何长度的数组的子集了!

下面把代码给大家

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

void nums_add(int* arr, int len) {
    if (len == 1) {
        *arr = 1;
        return;
    }
    else if (*arr == 1) {
        *arr = 0;//加一后变成零了
        nums_add(arr + 1, len - 1);//让后面一位加一,然后剩余长度减一
    }
    else if(*arr==0){
        *arr=1;//0加成1
    }
}

void nums_add_(int* arr, int len) {
    int k = len,i=0;
    while (1) {
        if (k == 1) {
            arr[i] = 1;//如果长度为1了就退出
            return;
        }
        if (arr[i] == 1) {
            arr[i] = 0;
            ++i;
            --k;
            continue;//如果要进一我们还要循环一次,所以用continue
        }
        else if (arr[i] == 0) {
            arr[i] = 1;
        }
        return;//到这里表示从0加到一,我们就不需要再循环了,直接结束循环
    }
}
int main() {
    int n = 0;
    scanf("%d", &n);
    int* arr = (int*)malloc(n * sizeof(int));
    if (!arr)return -1;
    for (int x = 0; x < n; ++x) {
        scanf("%d", arr + x);
    }

    int* nums = (int*)calloc(n+1, sizeof(int));
    int m[3];
    while (1) {
        nums_add_(nums, n + 1);
        if (nums[n] == 1)break;
        int k = 0;
        for (int x = 0; x < n; ++x) {
            if (nums[x] == 1)
            {
                if (k == 3)break;//已经有三个了还要存,直接跳过这个
                m[k++] = arr[x];
            }
        }
        if (k!=3)continue;//如果不等于三个,直接跳过到下一个循环
        printf("%d %d %d",m[0],m[1],m[2]);
        printf("\n");
    }
    return 0;
}

因为递归会开辟内存,所以后面的代码我们都用第二种非递归的

取出长度固定的所有子集

如果我们只要里面长度为3的子集怎么办呢?

自增变量来判断

我们可以在for循环里面先用一个长度为三的数组来存储我们的数据,再用一个变量来看是否满足。满足就打印。

在递归/非递归的时候就检测好

递归的时候我们完全就可以把1的数量统计好,所以可以做以下改变

但是这样也没怎么变化嘛,那么我们既然可以知道1了,我们再储存一下有1的数组的位置可以吧?

这里我们发现是反着来的,我们把打印的顺序反过来就行了。因为这里的m数组相当于栈

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

void nums_add(int* begain_arr, int* arr, int* m, int* p, int len, int* number) {
    if (len == 1) {
        *arr = 1;
        return;
    }
    else if (*arr == 1) {
        *arr = 0;//加一后变成零了
        --(*number);
        if (*p>0) {
            --p;
        }
        nums_add(arr,arr + 1,m,p, len - 1,number);//让后面一位加一,然后剩余长度减一
    }
    else if(*arr==0){
        ++(*number);
        *arr=1;//0加成1
        if (*p < 3) {
            m[(*p)++] = (int)(arr - begain_arr);
        }
    }
}

void nums_add_(int* arr,int*m,int *p,int len, int*number) {
    int k = len,i=0;
    while (1) {
        if (k == 1) {
            arr[i] = 1;//如果长度为1了就退出
            return;
        }
        if (arr[i] == 1) {
            arr[i] = 0;
            --(*number);
            ++i;
            --k;
            if (*p>0) {
                --(*p);
            }
            continue;//如果要进一我们还要循环一次,所以用continue
        }
        else if (arr[i] == 0) {
            arr[i] = 1;
            ++(*number);
            if (*p < 3) {
                m[(*p)++] =i;
            }
        }
        return;//到这里表示从0加到一,我们就不需要再循环了,直接结束循环
    }
}
int A_(int m, int n) {//非递归型
    int k = 1, i = m, j = n;
    while (1) {
        if (i == 1)return k * j;
        else {
            k *= j;
            --i;
            --j;
        }
    }
}
int C_(int m, int n) {
    return m == 0 ? 1 : A_(m, n) / A_(m, m);
}
int main() {
    int n = 0;
    scanf("%d", &n);
    int* arr = (int*)malloc(n * sizeof(int));
    if (!arr)return -1;
    for (int x = 0; x < n; ++x) {
        scanf("%d", arr + x);
    }

    int* nums = (int*)calloc(n+1, sizeof(int));
    int m[3] , p = 0 , number1 = 0;//定义number1存储我们的1的数量
    while (1) {
        nums_add_(nums,m,&p, n + 1, &number1);
        if (nums[n] == 1)break;
        int k = 0;
        if (number1 != 3)continue;
        printf("%d %d %d",m[2],m[1],m[0]);
        printf("\n");
    }
    return 0;
}

那么我们第一部分终于也是完成了,我嘞个豆真是多!!!!!!!!!!!!!!!!!!!!!!!!!

a,b的最小公倍数和最大公约数

我们题目要求的是最小公倍数,那么求这个我们可以枚举,但是时间复杂度复很高,所以我们就有特殊的算法。

我们首先要了解一个知识点就是

a*b=最大公约数(a,b)*最小公倍数(a,b)

我们求最小公倍数可能没有优秀的算法,但是我们最大公约数有优秀的算法。那么就可以通过这个式子进行转化。

辗转相除法求最大公约数

举个例子:求16 和 24的最大公约数

                24%16 =8

                16%8 = 0

                所以答案是8 

如果开始两个数字交换呢?

                16%24=16

                24%16=8 

                16%8=0

我们发现就是多了一部,没有太大差别。

那么我们开始实现

这里return的是最大公约数。

如果求三者的最大公约数或者最小公倍数,把其中两个数的先求出来,再看成整体和另一个求。

S

那么图中的表达式我们就可以算了

这里同样的,先除法再乘法,防止溢出了。

创建二维数组来存储三个都是1的数据。

我们就要用一个二维数组来储存我们的数据。那么每一个数组的长度是多少呢?

根据组合数我们要C(3,n)长度。排列组合在编程里面也很常见,我们也要知道他是怎么算出来的,排列组合我在下面讲到

排列组合函数

先是讲A(m,n)

如果m=n,那么就是算的阶乘。

我们可以通过A(m,n)=A(m-1,n-1)*n   来计算

C(m,n)

它有两个公式可以算,一个是C(m,n)=A(m,n)/A(n,n)  另一个是C(m,n)=n!/m!/(n-m)!

那么那个好呢?当然是第一个,第一个数字间相乘的次数少,不容易溢出。

储存后方便我们后面再取。

我们再用一个变量来存储S的最大值

那么我们的宝石问题就完成了。

真的完成了吗?

no no no

存储根本不需要二维数组,我写到这才发现,我们只要用一个长度为3个数组来储存最大的数据就行了

那么我们的排列组合函数就不需要了。

另外补充

我们m数组的长度定义的太短了,会产生越界访问。所以可以将m数组的长度定义长一点。可以和arr的数组一样长.

提前排序来解决字典序要求

我们的代码已经可以计算了,但是还有最后一个坑。例如我们逆向输入

因为S(5,4,3)和S(1,2,3)的值是一样的,所以我们不会存后面字典序小的数据。我们最要先将数据进行排序。

这里我们光速搓一个快排出来

在计算之前排好序就行了。

最终的代码

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/819980.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LinuxShell编程中source和export命令

目录 1.source命令1.1.POSIX模式1.1.1.验证POSIX模式执行情况 1.2.source命令表示形式的历史由来1.3.source命令解读1.3.1.在当前的shell环境中1.3.2.source命令的常用用途1.3.3.从文件名中读取并执行命令 2.export命令2.1.显示当前终端已经导出的函数和环境变量2.2.验证变量和…

Python异常处理机制详解及示例

Python异常处理机制详解及示例 在编程过程中&#xff0c;异常处理是一项至关重要的技能。Python作为一种功能强大的编程语言&#xff0c;提供了一套完善的异常处理机制&#xff0c;使得程序在遇到错误或异常情况时能够优雅地处理&#xff0c;而不是直接崩溃。本文将详细介绍Py…

MySQL——基础

SQL 全称 Structured Query Language&#xff0c;结构化查询语言。操作关系型数据库的编程语言&#xff0c;定义了一套操作关系型数据库统一标准 。 SQL 通用语法 SQL语句可以单行或多行书写&#xff0c;以分号结尾。SQL语句可以使用空格/缩进来增强语句的可读性。MySQL数据库…

一文速览铁威马TOS 6全新“文件管理”

TOS 6 Beta已经上线一段时间了&#xff0c;各位铁粉用着怎么样呢&#xff1f;今天就和大家分享&#xff0c;TOS 6全新文件管理。 为了向用户提供更流畅、更便捷的文件管理体验&#xff0c;铁威马的研发团队积极借鉴了Windows OS和Mac OS在文件管理方面的优点&#xff0c;投入巨…

【LeetCode刷题记录】41.缺失的第一个正数

41 缺失的第一个正数 给你一个未排序的整数数组 nums &#xff0c;请你找出其中没有出现的最小的正整数。 请你实现时间复杂度为 O(n) 并且只使用常数级别额外空间的解决方案。 示例 1&#xff1a; 输入&#xff1a;nums [1,2,0] 输出&#xff1a;3 解释&#xff1a;范围 [1…

设置coredump存储路径

设置coredump存储路径需要配置/proc/sys/kernel/core_pattern中的路径&#xff0c;一般情况下如下操作&#xff1a; echo /home/core-%e-%p >/proc/sys/kernel/core_pattern 但是这种方法在有的系统中会设置失败。例如ubuntu中。 因为ubuntu中默认开启了系统错误诊断&#x…

Redis实现持久化和集群的搭建

一、Redis的持久化方案 1&#xff09;RDB持久化 RDB&#xff08;Redis Database Backup file&#xff09;&#xff0c;Redsi数据备份文件或Redis数据快照。 把内存中的所有快照文件称为RDB文件&#xff0c;默认是保存在当前运行目录。 RDB持久化在四种情况下会执行&#xff…

[gvim] 操作

1. 删除操作 behaviorcode删除高亮内容:%s//g删除高亮内容所在行:g//d只删除匹配内容:%s/<pattern>//删除匹配内容所在的行:g/<pattern>/d只保留匹配内容的行:v/<pattern>/d 2. 替换操作 behaviorcode全局替换:%s/src_word/tgt_word/g替换n-m行关键字:n,m…

【echarts】echarts入门教程,学会如何编写echarts代码

echarts模板 使用&#xff01;为html来创建一个模板。 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><titl…

Open3D (C++) 点云投影至主成分空间

目录 一、算法原理二、代码实现三、结果展示四、相关连接Open3D (C++) 点云投影至主成分空间由CSDN点云侠原创,爬虫自重。如果你不是在点云侠的博客中看到该文章,那么此处便是不要脸的爬虫。 一、算法原理 p r o j

windeployqt工具

windeployqt是Qt SDK提供的一个实用工具&#xff0c;专为Windows平台设计&#xff0c;用于自动部署Qt应用程序所需的所有依赖库和组件。当你构建了一个Qt应用程序并希望在没有安装Qt开发环境的计算机上运行时&#xff0c;windeployqt工具能够帮你复制和收集应用程序运行所需的动…

原始部落版本潮玩宇宙小程序定制大逃杀游戏APP开发H5游戏

原始部落版本潮玩宇宙小程序定制大逃杀游戏APP开发H5游戏 潮玩宇宙小程序定制大逃杀游戏APP开发H5游戏 潮玩宇宙大逃杀小游戏模块成品源码&#xff0c;可嵌入任何平台系统&#xff0c;增加用户粘性&#xff0c;消除泡沫&#xff0c;短视频直播引流。 玩家选择一间房间躲避杀手…

第二期书生浦语大模型训练营第五次作业

部署LMDeploy并对话 配置LMDeploy运行环境 安装好环境&#xff0c;并成功激活 使用transformer运行大模型 使用LMDeploy模型量化(lite) KV8量化和W4A16量化。KV8量化是指将逐 Token&#xff08;Decoding&#xff09;生成过程中的上下文 K 和 V 中间结果进行 INT8 量化&#…

lua的字符串和Table类型实现

字符串 实现在lstring.c中。 字符串类型TString定义如下&#xff1a; typedef union TString {L_Umaxalign dummy; /* ensures maximum alignment for strings */struct {CommonHeader;lu_byte reserved;unsigned int hash;size_t len;} tsv; } TString;字符串内容紧随其后&a…

类方法,实例方法,静态方法对比

Date: 2024.04.16 实例方法&#xff1a;如果某一个方法需要访问到对象的实例属性&#xff0c;可以把这个方法封装成一个实例方法。 类方法&#xff1a;如果某一个方法不需要访问对象的实例属性&#xff0c;但是需要访问到类的类属性&#xff0c;这个时候就可以考虑把这个方法封…

Qt如何编写生成后事件

我们都知道VS能编写生成后事件&#xff0c;用于指定程序编译之后执行某些命令行&#xff0c;常见的如文件的拷贝、清理等等&#xff1b;那么&#xff0c;Qt能否支持支持在 .pro 文件中指定生成后事件呢&#xff0c;答案是肯定的。 下面是给出的一个简洁的例子&#xff1a; DEST…

【安装部署】Apache SeaTunnel 和 Web快速安装详解

版本说明 由于作者目前接触当前最新版本为2.3.4 但是官方提供的web版本未1.0.0&#xff0c;不兼容2.3.4&#xff0c;因此这里仍然使用2.3.3版本。 可以自定义兼容处理&#xff0c;官方提供了文档&#xff1a;https://mp.weixin.qq.com/s/Al1VmBoOKu2P02sBOTB6DQ 因为大部分用…

引领智能互联时代,紫光展锐赋能百业创新发展

随着5G技术的快速发展&#xff0c;各行各业对通信技术的需求也在不断升级。紫光展锐持续深耕5G垂直行业&#xff0c;不断推进5G标准演进&#xff0c;从R15到R16&#xff0c;再到R17&#xff0c;展锐携手生态合作伙伴&#xff0c;不断推出创新性解决方案&#xff0c;在5G RedCap…

发作性睡病可以通过饮食调理吗?

发作性睡病是一种慢性的睡眠障碍&#xff0c;患者在白天会出现无法控制的睡意&#xff0c;甚至可能突然入睡。虽然饮食不能直接治愈发作性睡病&#xff0c;但合理的饮食调整可以在一定程度上缓解症状&#xff0c;提高患者的生活质量。 首先&#xff0c;发作性睡病患者需要保持…

【Unity】RPG小游戏创建游戏中的交互

RPG小游戏创建游戏中的交互 创建可交互的物体的公共的父类&#xff08;Interactable&#xff09;InteractableObject 类NPCObject 类PickableObject 类 创建可交互的物体的公共的父类&#xff08;Interactable&#xff09; InteractableObject 类 using System.Collections; u…