【ICPC 2020上海区域赛】Traveling in the Grid World(平面几何)
发布日期:2021-06-27 15:38:10 浏览次数:3 分类:技术文章

本文共 3062 字,大约阅读时间需要 10 分钟。

题面

在这里插入图片描述

如果此时 n , m ≤ 1 0 18 n,m \leq 10^{18} n,m1018 怎么办呢?

题解

题意都明白吧,从 A ( 0 , 0 ) A(0,0) A(0,0) B ( n , m ) B(n,m) B(n,m) 连一条由线段组成的折线路径,要求如题。

如果 n , m n,m n,m 互质的话,直接欧几里得距离就行了,

那要是不互质呢?就不能一条线段连过去了

我们可以证明,最多两条线段,是可以连过去的,最优的答案一定中间只有一个折点。


我们用调整法证明两个推论:

  1. 任意一个两条线段组成的折线路径,如果非端点的部分经过了整点,则一定可以调整为一条更优的路径。
  2. 如果存在一条超过两条线段的折线路径,一定能调整为一个更优的两条线段组成的路径。

首先证明第一条,如图,这是一条不合法的折线,上面有个整点为 C:

在这里插入图片描述
很直观地,我们把 B 和 C 相连,那么 A → C → B A→C→B ACB A → M → B A→M→B AMB 更优,
在这里插入图片描述
因为 △ B C M △BCM BCM两边之和大于第三边
如果此时AC或者BC上还有一个整点D,那么就重复上述过程,一定最终会得到一条合法路径,且一次比一次更优。

我们再证明第二个推论,如图是一条挺曲折的路径(由折线组成):

在这里插入图片描述
由于它是折线,所以一定存在一个中间的端点 C,满足 A , B , C A,B,C A,B,C 三点不共线(这个应该不用证了吧,稍微反推一下就好),然后把 C 分别连向 A 和 B,由于两点之间线段最短,所以 A → C → B A\rightarrow C\rightarrow B ACB 一定更优。此时若不合法,再通过上文的第一条推论调整即可。


好,那么我们明确了答案一定为两条线段了,接下来我们通过这一点来做:

最优答案一定在离 AB 最近的、有格点的、与 AB 平行的直线上

(自我感觉这挺显然的,并且国集爷讲到这儿时觉得过于显然跳过了,虽然这很正常,但是放开想一下会感觉有反例,如果不严谨证明一下是不行的。看官们可以在找一下证明,笔者真不会证🙉,谅解一下谢谢)

怎么找这样一个点呢? 因为直线与AB平行,所以它一定在这样一条线上:

y = m n x + c y=\frac{m}{n}x + c y=nmx+c ,其中在有整点的前提下,c 要最小,

我们把它先约分一下,

N = n g c a ( n , m )    ,    M = m g c d ( n , m ) N=\frac{n}{gca(n,m)}\;,\;M=\frac{m}{gcd(n,m)} N=gca(n,m)n,M=gcd(n,m)m,
则可以变成 y = M N x + c , ( N , M 互 质 ) y=\frac{M}{N}x + c,(N,M 互质) y=NMx+c,(N,M)

再变一下式:

N y = M x + N c N y − M x = N c N ( y ) + M ( − x ) = N c Ny = Mx + Nc\\ Ny-Mx=Nc\\ N(y)+M(-x)=Nc Ny=Mx+NcNyMx=NcN(y)+M(x)=Nc
我们知道,这样一个不定方程有整数解当且仅当 N c Nc Nc g c d ( N , M ) = 1 gcd(N,M)=1 gcd(N,M)=1 的倍数,由于 c 可以是任意实数(我们并没说过 c 一定是整数吧),所以 c 最小可以是 1 N \frac{1}{N} N1 ,这时 N c = 1 Nc=1 Nc=1,方程的特解可以由得出,假设特解为 ( x ′ , y ′ ) (x',y') (x,y),那么通解为
( x , y ) = ( x ′ , y ′ ) + k ⋅ ( N , M ) (x,y)=(x',y')+k\cdot (N,M) (x,y)=(x,y)+k(N,M)

然后,就是一个简单的初中几何题了

在这里插入图片描述
(经典老对称)只用找距离 A’B 和 y = M N x + c y=\frac{M}{N}x+c y=NMx+c 的交点最近的那个格点,这个可以三分,也可以暴力数学推导O(1)做。

所以这道题, n , m ≤ 1 0 18 n,m\leq 10^{18} n,m1018 也不怕,一样可以 O ( T l o g n ) O(Tlogn) O(Tlogn) 解决。

CODE

(笔者为了节省时间就只打了个exgcd暴力应付这道题,供对拍用,大家有兴趣可以尝试 O ( T l o g n ) O(Tlogn) O(Tlogn) 的解法)

#include#include
#include
#include
#include
#include
#include
#include
using namespace std;#define MAXN 1005#define LL long long#define ULL unsigned long long#define DB double#define ENDL putchar('\n')#define lowbit(x) ((-(x)) & (x))LL read() { LL f = 1,x = 0;char s = getchar(); while(s < '0' || s > '9') { if(s=='-')f = -f;s = getchar();} while(s >= '0' && s <= '9') { x=x*10+(s-'0');s = getchar();} return x * f;}const int MOD = 1000000007;int n,m,i,j,s,o,k;int exgcd(int a,int b,int &x,int &y) { if(b == 0) { x=1;y=0;return a;} int r = exgcd(b,a % b,y,x); y -= x*(a/b); return r;}DB dis(int x,int y,int a,int b) { return sqrt((DB)(x-a)*1.0*(x-a) + (y-b)*1.0*(y-b));}int main() { int T = read(); while(T --) { n = read();m = read(); int x,y,N,M; int gc = exgcd(n,m,y,x); x = -x; if(gc == 1) { printf("%.10f\n",dis(0,0,n,m)); continue; } N = n/gc;M = m/gc; while(x > 0 && y > 0) x -= N,y -= M; while(x < 0 || y < 0) x += N,y += M; DB ans = 1e18; while(x < n && y < m) { ans = min(ans,dis(0,0,x,y) + dis(x,y,n,m)); x += N;y += M; } printf("%.10f\n",ans); } return 0;}

转载地址:https://blog.csdn.net/weixin_43960414/article/details/112298753 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:2020年信竞说
下一篇:后缀自动机算法复习回顾

发表评论

最新留言

不错!
[***.144.177.141]2024年04月25日 04时17分52秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章

升职加薪必看!读完我这份《Android开发核心源码精编解析》面试至少多要3K!附答案 2019-04-29
华为架构师深入讲解Android开发!为什么Flutter能最好地改变移动开发?吐血整理 2019-04-29
基于安卓的兼职app开发!万字长文轻松彻底入门Flutter,终获offer 2019-04-29
大牛深入讲解!2021年Android网络编程总结篇,书籍+视频+学习笔记+技能提升资源库 2019-04-29
大牛深入讲解!算法题+JVM+自定义View,大厂内部资料 2019-04-29
太厉害了!记录一次腾讯Android岗面试笔试总结,全套教学资料 2019-04-29
如何成为杰出的程序员?阿里P8架构师的Android大厂面试题总结,已拿到offer 2019-04-29
字节跳动社招面试记录,关于网络优化你必须要知道的重点,附面试题答案 2019-04-29
大牛手把手带你!宅家36天咸鱼翻身入职腾讯,经典好文 2019-04-29
大牛深入讲解!Android高级工程师面试实战,一线互联网公司面经总结 2019-04-29
如何成为杰出的程序员?2021年Android高级面试题,2年以上经验必看 2019-04-29
字节跳动社招面试记录,2021年上半年最接地气的Android面经,实战解析 2019-04-29
学习安卓开发!我凭什么拿到了阿里、腾讯、今日头条3家大厂offer?再不刷题就晚了! 2019-04-29
安卓3d游戏开发视频!春招我借这份PDF的复习思路,完整版开放下载 2019-04-29
安卓app开发!大厂Offer拿到手软啊!年薪超过80万! 2019-04-29
安卓ndk开发!高级Android晋升之View渲染机制,附答案 2019-04-29
安卓开发交流!Android程序员架构之路该如何继续学习?含爱奇艺,小米,腾讯,阿里 2019-04-29
安卓开发网!Android面试知识点总结宝典助你通关!含泪整理面经 2019-04-29
安卓开发者!京东面试真题解析,移动架构师成长路线 2019-04-29
查漏补缺!Android开发还会吃香吗?Android面试题及解析 2019-04-29