C++蓝桥杯皮亚诺曲线距离求解
C++蓝桥杯皮亚诺曲线距离求解
- 一、题目概述
- 二、解题分析
- 2.1解题思路
- 2.2k值范围限制
- 三、实现代码
- 四、代码测试
- 4.1蓝桥杯测试平台
- 4.2直接传入原始输入的k值
- 4.3限制k值大小
- 4.4pow函数求整数高次幂存在误差
- 4.5满分代码
- 附录
- error: ‘long long int y1’ redeclared as different kind of symbol报错
- C++中int类型与long long类型取值范围
一、题目概述
给定指定阶数的皮亚诺曲线,以及曲线上的两个点的坐标,求解两个点之间的距离,曲线起点坐标规定为(0,0)。
一阶皮亚诺曲线如下图:
k+1阶的皮亚诺曲线是在k阶曲线的基础上,每一个格子由一阶曲线代替而生成。例如二阶曲线如下图:
三阶曲线如下图:
k阶曲线的边长为3的k次幂,格子总数为3的2k次幂。无论k取何值,曲线的起点总为左下角,坐标为(0,0),终点为右上角,坐标为(3的2k次幂-1,3的2k次幂-1)。
二、解题分析
2.1解题思路
经过初步分析:
- 如果直接求解两点间的距离,那么需要求解任意两点间的详细路径,难度很大;
- 可以将求两点间距离转换为求出到原点的距离然后相减;
- k+1阶曲线是在1阶曲线的基础上层层细化网格而成,那么任意一点到原点的距离也可以先从宏观处入手,层层细化求解。
一阶曲线按照从起点到终点的行走顺序对网格进行划分,那么可分为1~9个区域,如下图所示:
任意k阶曲线都可以划分为上图所示的9个区域,例如二阶曲线划分如下图:
假设k阶曲线上的任意一点,该点到原点的距离=该点到所在区域起点的距离+本区域之前的区域网格数累加和,而该点到所在区域起点的距离又可以转换为以所在区域起点为原点的求解到原点距离的问题,因此可以层层递归求解。
根据上述解题思路,细化解题步骤如下:
- 首先判断出k阶曲线上任意一点(x,y)所在区域,每个区域的边长为3的k-1次幂,因此可以通过对比大小得出判断;
- 点到所在区域起点的距离如果要转换为以所在区域起点为原点的点到该原点的距离,就要将区域的起点映射为区域1的起点,即原点,该映射不仅仅是平移,可能还要旋转;
- 以二阶曲线为例,区域2的起点转换为区域1的起点。区域2的起点坐标为(2,3),如果要转换到(0,0),那么就需要进行映射(2-x,y-3),(x,y)为区域2内的点,2-x说明区域2进行了X轴方向的翻转;
- 本区域之前的区域网格数累加计算较为简单,每个区域的网格数为3的2k-2次幂,例如区域5之前的区域网格数累加,就等于4×3的2k-2次幂。
解题步骤大致如上,读者对皮亚诺曲线随阶数的增加而在形状上层层裂变的过程有一个形象的想象过程,有助于理解解题步骤。
2.2k值范围限制
由于题目中说明k值范围为1~100,而点的坐标的范围为不超过10的18次方,显然3的100次幂超过了10的18次方,同时也超过了C++中long long类型可表示的范围,因此不能直接将k值代入进行求解,而是要先判断出在10的18次方范围内的最大k值,判断代码如下:
void test_k()
{int k=0;long long p1;while(true){p1=pow(3, k);if(p1>=1e18)break;k++;}cout<<k<<endl;cout<<p1<<endl;
}
得出k值最大为38。
三、实现代码
代码使用C++实现,如下:
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;int k;
long long x11,y11,x12,y12;long long func01(long long x, long long y, int k)
{if(k == 0) return 0;long long tmp=pow(3, k-1);if(x < tmp && y < tmp) return func01(x, y, k-1);//region1 if(x < tmp && (y >= tmp && y < tmp*2)) return tmp*tmp + func01(tmp-1-x, y-tmp, k-1);//region2if(x < tmp && (y >= tmp*2 && y < tmp*3)) return 2*tmp*tmp + func01(x, y-tmp*2, k-1);//region3if((x >= tmp && x < tmp*2) && y < tmp) return 5*tmp*tmp + func01(x-tmp, tmp-1-y, k-1);//region6if((x >= tmp && x < tmp*2) && (y >= tmp && y < tmp*2)) return 4*tmp*tmp + func01(tmp*2-1-x, tmp*2-1-y, k-1);//region5if((x >= tmp && x < tmp*2) && (y >= tmp*2 && y < tmp*3)) return 3*tmp*tmp + func01(x-tmp, tmp*3-1-y, k-1);//region4if((x >= tmp*2 && x < tmp*3) && y < tmp) return 6*tmp*tmp + func01(x-tmp*2, y, k-1);//region7if((x >= tmp*2 && x < tmp*3) && (y >= tmp && y < tmp*2)) return 7*tmp*tmp + func01(tmp*3-1-x, y-tmp, k-1);//region8if((x >= tmp*2 && x < tmp*3) && (y >= tmp*2 && y < tmp*3)) return 8*tmp*tmp + func01(x-tmp*2, y-tmp*2, k-1);//region9return -1;
}int main()
{cin>>k;cin>>x11>>y11;cin>>x12>>y12;if(k > 38) k=38;cout<<abs(func01(x11,y11,k)-func01(x12,y12,k))<<endl;return 0;
}
此题代码并不长,关键在于解题思路。
四、代码测试
4.1蓝桥杯测试平台
为测试代码正确性,可以在蓝桥杯的刷题平台提交代码,网址为https://www.lanqiao.cn/problems/?first_category_id=1。
皮亚诺曲线距离题目编号为141,如下图所示:
4.2直接传入原始输入的k值
在蓝桥杯解题平台对代码进行测试,当将k值直接传入递归函数时,可以得到90%的分数,显示10个测试实例中有一个答案错误,如下图所示:
在本地运行代码,发现确实是因为3的100次方超出了long long类型的范围,导致错误输出。
4.3限制k值大小
对k值大小进行限制,采用了本文第三节中给出的代码,在蓝桥杯平台提交,结果依然显示10个测试实例中有一个答案错误,后将该错误实例的输入数据与输出数据下载到本地,测试数据如下:
k | x11 | x12 | y11 | y12 |
---|---|---|---|---|
100 | 972800214282722763 | 781912860110024270 | 972800214336621164 | 781912860202693276 |
正确输出应为191503939959914635。
在本地运行程序,得到的输出为191503939959943987,确实与答案不一致,经过一番检查后发现,是由于pow函数导致的答案错误。
4.4pow函数求整数高次幂存在误差
分别使用pow函数求3的k次幂与连续乘积计算3的k次幂测试结果的一致性,代码如下:
void test_pow()
{int k=1;long long p1,p2=1;while(true){p1=pow(3, k);p2*=3;if(p1>=1e18)break;k++;cout<<p1<<','<<p2<<endl;}cout<<k<<endl;cout<<p1<<endl;
}
输出如下图:
从输出结果分析,当k≥35时,两种方法计算出的3的k次幂出现了不同,且差异会越来越大。通过查找资料得知:pow函数返回的是double类型,在被强制转换为整型时会出现误差。
4.5满分代码
因此代码中不再使用pow函数,而是通过连续乘积计算幂,最终代码如下:
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;int k;
long long p[100];
long long x11,y11,x12,y12;long long func01(long long x, long long y, int k)
{if(k == 0) return 0;//long long tmp=pow(3, k-1);long long tmp=p[k-1];if(x < tmp && y < tmp) return func01(x, y, k-1);//region1 if(x < tmp && (y >= tmp && y < tmp*2)) return tmp*tmp + func01(tmp-1-x, y-tmp, k-1);//region2if(x < tmp && (y >= tmp*2 && y < tmp*3)) return 2*tmp*tmp + func01(x, y-tmp*2, k-1);//region3if((x >= tmp && x < tmp*2) && y < tmp) return 5*tmp*tmp + func01(x-tmp, tmp-1-y, k-1);//region6if((x >= tmp && x < tmp*2) && (y >= tmp && y < tmp*2)) return 4*tmp*tmp + func01(tmp*2-1-x, tmp*2-1-y, k-1);//region5if((x >= tmp && x < tmp*2) && (y >= tmp*2 && y < tmp*3)) return 3*tmp*tmp + func01(x-tmp, tmp*3-1-y, k-1);//region4if((x >= tmp*2 && x < tmp*3) && y < tmp) return 6*tmp*tmp + func01(x-tmp*2, y, k-1);//region7if((x >= tmp*2 && x < tmp*3) && (y >= tmp && y < tmp*2)) return 7*tmp*tmp + func01(tmp*3-1-x, y-tmp, k-1);//region8if((x >= tmp*2 && x < tmp*3) && (y >= tmp*2 && y < tmp*3)) return 8*tmp*tmp + func01(x-tmp*2, y-tmp*2, k-1);//region9return -1;
}int main()
{cin>>k;cin>>x11>>y11;cin>>x12>>y12;if(k > 38) k=38;p[0]=1;for(int i = 1; i <= k; i++) p[i]=p[i-1]*3;cout<<abs(func01(x11,y11,k)-func01(x12,y12,k))<<endl;return 0;
}
上述代码提交后,全部10个用例全部跑通。
附录
error: ‘long long int y1’ redeclared as different kind of symbol报错
初始编写上述代码时,第一个点的坐标变量本来定义为x1,y1,代码在本地Dev-C++编译器上能够正确运行,但是在蓝桥杯解题平台上运行就报出该错误,后经查找资料后发现,cmath头文件中定义了与y1同名的函数,所以导致报错,因此上述代码中的变量名改为x11,y11,x12,y12。
C++中int类型与long long类型取值范围
类型 | 专用存储空间 | 表示范围 | 次方表示 |
---|---|---|---|
int | 4个字节 | -2,147,483,648~2,147,483,647 | − 2 31 -2 ^{31} −231 ~ 2 31 2 ^{31} 231-1,约为10的9次方 |
unsigned int | 4个字节 | 0~4,294,967,295 | 0 ~ 2 32 2 ^{32} 232-1,约为10的9次方 |
long | 4个字节 | -2,147,483,648~2,147,483,647 | − 2 31 -2 ^{31} −231 ~ 2 31 2 ^{31} 231-1,约为10的9次方 |
unsigned long | 4个字节 | 0~4,294,967,295 | 0 ~ 2 32 2 ^{32} 232-1,约为10的9次方 |
long long | 8个字节 | -9,223,372,036,854,775,808~9,223,372,036,854,775,807 | − 2 63 -2 ^{63} −263 ~ 2 63 2 ^{63} 263-1,约为10的18次方 |
unsigned long long | 8个字节 | 0~18,446,744,073,709,551,615 | 0 ~ 2 64 2 ^{64} 264-1,约为10的19次方 |
相关文章:

C++蓝桥杯皮亚诺曲线距离求解
C蓝桥杯皮亚诺曲线距离求解 一、题目概述二、解题分析2.1解题思路2.2k值范围限制 三、实现代码四、代码测试4.1蓝桥杯测试平台4.2直接传入原始输入的k值4.3限制k值大小4.4pow函数求整数高次幂存在误差4.5满分代码 附录error: ‘long long int y1’ redeclared as different kin…...

【语料数据爬虫】Python爬虫|批量采集工作报告数据(1)
前言 本文是该专栏的第4篇,后面会持续分享Python爬虫采集各种语料数据的的干货知识,值得关注。 在本文中,笔者将主要来介绍基于Python,来实现批量采集“工作报告”数据。同时,本文也是采集“工作报告”数据系列的第1篇。 采集相关数据的具体细节部分以及详细思路逻辑,笔…...

【音视频】ffmpeg命令提取像素格式
1、提取YUV数据 提取yuv数据,并保持分辨率与原视频一致 使用-pix_fmt或-pixel_format指定yuv格式提取数据,并保持原来的分辨率 ffmpeg -i music.mp4 -t "01:00" -pixel_format yuv420p music.yuv提取成功后,可以使用ffplay指定y…...

6-langchang多模态输入和自定义输出
6-langchang多模态输入和自定义输出 多模态数据输入urlbase64url list工具调用自定义输出: JSON, XML, YAML如何解析 JSON 输出json如何解析xmlYAML解析器多模态数据输入 这里我们演示如何将多模态输入直接传递给模型。我们目前期望所有输入都以与OpenAI 期望的格式相同的格式…...

STM32上跑SimpleFOC,电流环、速度环、位置环、棘轮软硬件全开源
引入 我之前写过不少SVPWM、FOC的介绍文章,比如: SVPWM算法原理及详解 从电机本质到park变换再到SVPWM,SVPWM代码实现 电机FOC算法的解释 FOC和SVPWM的C语言代码实现 simple foc可以看成是他们的简化版本。本来simple foc是跑在arduino上的…...

智慧锂电:开启能源新时代的钥匙
在科技日新月异的今天,智慧锂电正以其独特的魅力,引领着能源领域的新变革。智慧锂电不仅革新了传统电池技术,更以其智能化、高效化的特性,成为推动能源管理现代化的重要力量。 智慧锂电项目:点亮绿色转型之路 智慧锂电…...

密码学 网络安全 科普 网络安全密码技术
网络加密包括密码技术和网络加密方法两个方面。 一、 密码技术 密码技术一般分为常规密码和公钥密码。 常规密码是指收信方和发信方使用相同的密钥,即加密密钥和解密密钥是相同或等价的。比较著名的常规密码算法有DES及其各种变形、IDEA、FEAL、Skipjack…...

C# BlockingCollection
什么是 BlockingCollection<T>主要特点构造函数常用方法生产者操作消费者操作 示例代码注意事项串口接收底层存储的类型线程安全和并发访问串口数据接收的顺序性关键点 BlockingCollection<T> 是 C# 中一个非常有用的线程安全集合类,位于 System.Coll…...

学习笔记11——并发编程之并发关键字
并发关键字 synchronized关键字 在应用Sychronized关键字时需要把握如下注意点: 1.一把锁只能同时被一个线程获取,没有获得锁的线程只能等待; 2.每个实例都对应有自己的一把锁(this),不同实例之间互不影响;例外:锁…...

2.2 Windows本地部署DeepSeek模型 --- Ollama篇(下)
2.3Ollama加载已下载Deepseek模型 无网络连接,直接通过Ollama本地已经本地已经下载好的的Deepseek模型。 2.3.1 查看已安装模型 PS C:\Users\Administrator> ollama list NAME ID SIZE MODIFIED deepseek-r1:8…...

DeepSeek R1-32B医疗大模型的完整微调实战分析(全码版)
DeepSeek R1-32B微调实战指南 ├── 1. 环境准备 │ ├── 1.1 硬件配置 │ │ ├─ 全参数微调:4*A100 80GB │ │ └─ LoRA微调:单卡24GB │ ├── 1.2 软件依赖 │ │ ├─ PyTorch 2.1.2+CUDA │ │ └─ Unsloth/ColossalAI │ └── 1.3 模…...

mysql的锁--一篇读懂所有锁机制
目录 mysql的锁 概述:根据mysql锁的大类型可以分为 我们先来讲一下范围最大的全局锁 使用 为什么要使用全局锁? 使用全局锁进行备份的缺点 表级锁 表锁 1.共享读表锁的语法 2.排斥写表锁 元数据锁 意向锁 什么是意向锁 怎么产生意向锁 意向…...

LTC6804、LTC6811、LTC6813的使用
FSEC自制BMS第一步:从零开发使用LTC6804采集电池电压 LTC6811特性 LTC6811 是 LTC6804 的引脚兼容型升级器件,LTC6804官方已经不推荐选用 可测量多达 12 节串联电池 1.2mV 最大总测量误差 可堆叠式架构能支持几百个电池 内置 isoSPI™ 接口 可在 290μ…...

linux内存页块划分及位图存储机制
page_alloc.c - mm/page_alloc.c - Linux source code v5.4.285 - Bootlin Elixir Cross Referencer 一. 什么是页块(Pageblock)? 定义:页块是物理内存中的一个连续区域,由 2^pageblock_order 个物理页(Pag…...

Vue 文件下载功能的跨域处理与前后端实现详解
在 Web 应用开发中,文件下载功能是常见需求。但由于跨域限制和认证机制的复杂性,实际开发中常遇到下载失败或权限错误等问题。本文将结合 Vue 前端和 Spring Boot 后端,详细介绍文件下载功能的实现与跨域问题的解决方案。 一、问题背景 在某…...

boost::beast websocket 实例
环境:ubuntu 1. 安装boost sudo apt install -y libboost-all-dev 2. Server端 #include <boost/asio.hpp> #include <boost/beast.hpp> #include <iostream> #include <thread>namespace beast boost::beast; // 从 Boost.Beast 中导…...

复试难度,西电卓越工程师学院(杭研院)考研录取情况
01、卓越工程师学院各个方向 02、24卓越工程师学院(杭研院)近三年复试分数线对比 PS:卓越工程师学院分为广研院、杭研院 分别有新一代电子信息技术、通信工程、集成电路工程、计算机技术、光学信息工程、网络信息安全、机械,这些…...

Rabbitmq--延迟消息
13.延迟消息 延迟消息:生产者发送消息时指定一个时间,消费者不会立刻收到消息,而是在指定时间之后才会收到消息 延迟任务:一定时间之后才会执行的任务 1.死信交换机 当一个队列中的某条消息满足下列情况之一时,就会…...

cocos creator使用mesh修改图片为圆形,减少使用mask,j减少drawcall,优化性能
cocos creator版本2.4.11 一个mask占用drawcall 3个以上,针对游戏中技能图标,cd,以及多玩家头像,是有很大优化空间 1.上代码,只适合单独图片的,不适合在图集中的图片 const { ccclass, property } cc._decorator;c…...

C++ Qt开发成长之路,从入门到企业级实战项目,保姆级学习路线
Qt 介绍 Qt是一个跨平台的C图形用户界面应用程序开发框架,最初由挪威的Trolltech公司开发,后来被诺基亚收购,现在由Qt公司维护。它提供了丰富的工具和类库,使开发者能够轻松地创建各种类型的应用程序,包括桌面应用、移…...

JavaWeb后端基础(7)AOP
AOP是Spring框架的核心之一,那什么是AOP?AOP:Aspect Oriented Programming(面向切面编程、面向方面编程),其实说白了,面向切面编程就是面向特定方法编程。AOP是一种思想,而在Spring框…...

Uniapp实现地图获取定位功能
摘要:本文将手把手教你如何在Uniapp项目中集成地图功能、实现定位获取,并解决微信小程序、APP、H5三端的兼容性问题🚀🚀🚀 一、环境准备 地图平台选择 微信小程序:腾讯地图(强制使用)…...

批量将 Excel 转换 PDF/Word/CSV以及图片等其它格式
Excel 格式转换是我们工作过程当中非常常见的一个需求,我们通常需要将 Excel 转换为其他各种各样的格式。比如将 Excel 转换为 PDF、比如说将 Excel 转换为 Word、再比如说将 Excel文档转换为图片等等。 这些操作对我们来讲都不难,因为我们通过 Office 都…...
Flutter:StatelessWidget vs StatefulWidget 深度解析
目录 1. 引言 2. StatelessWidget(无状态组件) 2.1 定义与特点 2.2 代码示例 3. StatefulWidget(有状态组件) 3.1 定义与特点 3.2 代码示例 4. StatelessWidget vs StatefulWidget 对比 5. StatefulWidget 生命周期 5.1…...

Stream流学习
Stream流 把数据放进stream流水线,对数据进行一系列操作(中间方法),最后封装(终结方法)。 Stream.of()允许传入任何参数 常见中间方法 可以对数据进行链式(流水线)操作,但…...

多视图几何--恢复相机位姿/内参的几种方法
恢复相机位姿的几种方法 1分解投影矩阵 1.1投影矩阵分解为相机内外参矩阵的完整解析 投影矩阵(Projection Matrix)是计算机视觉中将三维世界点映射到二维像素坐标的核心工具,其本质是相机内参矩阵(Intrinsic Matrix)…...

[数据结构]堆详解
目录 一、堆的概念及结构 二、堆的实现 1.堆的定义 2堆的初始化 3堆的插入 编辑 4.堆的删除 5堆的其他操作 6代码合集 三、堆的应用 (一)堆排序(重点) (二)TOP-K问题 一、堆的概念及结构 堆的…...

领域驱动设计(DDD)与MVC架构:理念对比与架构选择
领域驱动设计(DDD)与MVC架构:理念对比与架构选择 一、架构之争的本质:业务复杂度驱动技术演进 在软件开发领域,没有银弹式的完美架构,只有适合当前业务场景的合理选择。MVC与DDD的区别本质上是业务复杂度与…...

牛客周赛:84:B:JAVA
链接:登录—专业IT笔试面试备考平台_牛客网 来源:牛客网 题目描述 import java.util.ArrayList; import java.util.Arrays; import java.util.Scanner; public class Main {public static void main(String[] args) {Scanner scanner new Scanner(S…...

【理想解法学习笔记】
目录 理想解法原理简介算法步骤属性值规范化方法代码示例 理想解法 原理简介 TOPSIS(Technique for Order Preference by Simi larity to IdealSolution)法是一种逼近理想解的排序方法。其基本的处理思路是:首先建立初始化决策矩阵,而后基于规范化后的初…...