当前位置: 首页 > news >正文

2025第16届蓝桥杯省赛之研究生组D题最大数字求解

2025第16届蓝桥杯省赛之研究生组D题最大数字求解

  • 一、题目描述
    • 1.1题干
    • 1.2输入范围
    • 1.3题目链接
  • 二、题目分析
  • 三、题目求解
    • 3.1求解步骤
    • 3.2完整C++代码
    • 3.3代码说明
    • 3.4代码提交
  • 四、小结

一、题目描述

1.1题干

我们有 n 个连续的整数 1,2,3,⋯,n,可以自由排列它们的顺序。

然后,我们把这些数字转换成二进制表示,按照排列顺序拼接形成一个新的二进制数。

我们的目标是让这个二进制数的值最大,并输出这个二进制对应的十进制表示

输入格式
输入一行包含一个正整数 n。

输出格式
输出一行包含一个整数表示答案。

时间限制:5s,内存限制:512MB。

1.2输入范围

对于 20% 的评测用例,1≤n≤10;
对于 40% 的评测用例,1≤n≤100;
对于 60% 的评测用例,1≤n≤500;
对于 80% 的评测用例,1≤n≤1000;
对于所有评测用例,1≤n≤10000。

1.3题目链接

目前蓝桥杯题库未放出该题,
洛谷平台链接为:https://www.luogu.com.cn/problem/P12186。
在这里插入图片描述

二、题目分析

通过阅读题目,首先分析出解题要点有两个,第一是如何将二进制数排序获得最大值,第二是要进行高精度运算

显然解题的难点是如何进行排序,但是在实际编程过程中发现如何高效进行高精度运算也是想要拿到满分的一个难点。

下面对如何排序进行分析:

  1. 两个二进制数进行比较,高位首先出现0的数较小,如果一个二进制数都由1组成,那么当然要排在首位;
  2. 而不都由1组成的数如何排序似乎没有一个清晰的规律,此题形式上与F题01串类似,但无法使用贪心算法
  3. 考虑到n是10的4次方量级,那么可以考虑对二进制数两两比较进行排序,使用sort函数,复杂度近似为nlogn,不会超时,而排序判断准则已经在第一条中分析得出。

三、题目求解

3.1求解步骤

步骤如下:

  1. 首先将1~n的整数化为二进制数,使用字符串存储二进制串;
  2. 根据高位首先出现0的数较小这一规则,可以使用字符串比较大小来得到组合顺序,s1+s2>s2+s1;
  3. 获得排序后,将n个二进制串组合成一个大的字符串
  4. 使用高精度乘法与加法,将得到的二进制串化为十进制,得到最终输出。

3.2完整C++代码

C++代码如下:

#include<bits/stdc++.h>
using namespace std;const int N1=1e4+10, N2=4*10;
int b[N1];
vector<int> ans1, ans2;
vector<string> vts;
int n;bool comp(int p, int q)
{return vts[p]+vts[q]>vts[q]+vts[p];
}int main()
{cin>>n;for(int i=1; i<=n; i++){b[i]=i-1;int j=i;string tmp="";while(j){tmp=to_string(j&1)+tmp;j>>=1;}vts.push_back(tmp);}sort(b+1, b+n+1, comp);string fs="";for(int i=1; i<=n; i++){fs+=vts[b[i]];}int num1=0; ans1.push_back(1);ans2.push_back(0);//cout<<fs<<'\n';for(int i=fs.size()-1; i>=0; i-=16){int t1=0,t2=1, t3=0;for(int k=i; k>=max(0, i-15); k--){if(fs[k]=='1'){t1+=t2;}t2<<=1;}if(i!=fs.size()-1){for(int k=0; k<ans1.size(); k++){ans1[k]*=(256*256);}}for(int k=0; k<ans1.size(); k++){if(k<ans1.size()-1){ans1[k+1]+=ans1[k]/10;ans1[k]%=10;}}t2=ans1.back();t3=ans1.size();while(t2>=10){ans1.push_back(t2/10);t2/=10;}for(int k=t3-1; k<ans1.size(); k++) ans1[k]%=10;for(int k=0; k<min(ans1.size(), ans2.size()); k++){ans2[k]+=ans1[k]*t1;}if(ans2.size()<ans1.size()){for(int k=ans2.size(); k<ans1.size(); k++) ans2.push_back(ans1[k]*t1);} for(int k=0; k<ans2.size(); k++){if(k<ans2.size()-1){ans2[k+1]+=ans2[k]/10;ans2[k]%=10;}}t2=ans2.back();t3=ans2.size();while(t2>=10){ans2.push_back(t2/10);t2/=10;}for(int k=t3-1; k<ans2.size(); k++) ans2[k]%=10;}for(int k=ans2.size()-1; k>=0; k--) cout<<ans2[k];return 0;
}

3.3代码说明

  1. 使用vector类型变量vts存储1~n整数转换成的二进制字符串,而后自定义排序规则comp,使用sort函数进行排序;
  2. 排序后按照顺序拼接所有二进制串存储到fs变量中;
  3. 为高效计算高精度乘法加法,将二进制串以16位为一组进行拆分计算类似于256进制计算
  4. ans1存储256的幂次,每个元素为10进制数,ans2存储最终的结果,每个元素为10进制数。

之所以以16位为一组进行拆分计算,是因为如果对二进制串逐位进行计算会超时,而以m位为一组进行拆分是一种提高高精度计算效率的算法,此外还有Karatsuba 乘法、多项式优化算法等提高效率的算法,读者可以进行尝试。

3.4代码提交

在这里插入图片描述
在洛谷平台上提交上述代码,可以拿到满分,而如果不进行高精度计算优化,只能拿到80%的分数,后面4组测试用例会超时。

四、小结

本题难点首先在于找到正确排序的方法,这一点可能需要一定的技巧和经验。其次需要对高精度计算进行优化,否则只能拿到80%的分数。而如果使用python语言进行解题,那么题目难度会下降,因为python可以直接进行计算,不须考虑高精度的问题。

相关文章:

  • 学习spark总结
  • 常见锁策略
  • 关系型数据库PostgreSQL vs MySQL 深度对比:专业术语+白话解析+实战案例
  • Customizing Materials Management with SAP ERP Operations
  • AI日报 - 2025年04月28日
  • (26)VTK C++开发示例 ---将点坐标写入PLY文件
  • Java多线程实现顺序执行
  • 界面打印和重定向同时实现
  • CodeGeeX 免费的国产AI编程助手
  • HikariCP 6.3.0 完整配置与 Keepalive 优化指南
  • SAP-pp 怎么通过底表的手段查找BOM的全部ECN变更历史
  • 【实战篇】数字化打印——打印格式设计器的功能说明
  • (25)VTK C++开发示例 --- 将点坐标写入.xyz文件
  • 复盘笔记1
  • JavaScript性能优化实战:从瓶颈定位到极致提速
  • UE5 在旋转A的基础上执行旋转B
  • UE5 NDisplay 单主机打包运行
  • Java8 后接口的用法总结
  • Kubernetes/KubeSphere 安装踩坑记:从 context deadline exceeded 到成功部署的完整排障笔记
  • 如何排查服务器中存在的后门程序
  • 安阳一村支书微信群骂村民被警方行拘,辩称对方先“污蔑造谣”
  • 中国纪检监察报刊文:要让劳动最光荣成为社会的崇高风尚
  • “一对一讨论诸多事宜”,泽连斯基披露此次特泽会更多细节
  • 俄罗斯称已收复库尔斯克州,普京发表讲话
  • 泰山景区管委会:未经审核同意不得擅自举办竞速类登山活动
  • 新希望去年归母净利润4.74亿同比增逾九成,营收降27%