首页 > 其他分享 >洛谷-P9830 题解

洛谷-P9830 题解

时间:2024-08-05 20:49:45浏览次数:10  
标签:推论 洛谷 gcd double 题解 格点 ans P9830 dis

思路分析

分析样例:

见红线,长宽各为 2,存在格点;黄线长 2 宽 3,没有格点。

考虑延长黄线使得长 4 宽 6,发现有格点。思考格点,如果长和宽都可以被分成 \(p\times l\) 的格式,则存在格点。那么,就能想出:

推论 1:对于 \((0 \ , \ 0)\) 和 \((x \ , \ y)\) 之间没有格点,当且仅当 \(\gcd(x \ , \ y )=1\)。

对推论 1 的证明:

若存在格点 \(A\),其坐标为 \((a \ , \ b)\),由于在同一直线上,斜率 \(k\) 相同,则有 \(k=\dfrac{a}{b}=\dfrac{x}{y}\),即 \(b=\dfrac{a\times y}{x}\)。由于 \(b\) 为整数,则有 \(x \ | \ a\times y\)。

采用反证法,\(\gcd(x \ , \ y )=1\) 时存在格点。

由于互质,\(x=\prod\limits_{i=1}^{s1}p_i^{c_i} \ , \ y=\prod\limits_{i=1}^{s2}q_i^{d_i}\),假设 \(x \ | \ y\),\(y\) 必然有因子 \(\prod\limits_{i=1}^{s1}p_i^{c_i}\),而实际上没有,所以 \(y\) 对该式没有贡献。即:$x \ | \ a\times y \Leftrightarrow x \ | \ a $。

而 \(A\) 是线段上一点,有 \(a<x\),则 \(b\) 一定不属于 \(\mathbb{Z^+}\),与原有条件冲突,由此可证。

得出推论 1 后,我们就能判断两点之间是否有格点了。那么如何得出最短答案呢?

(图是随手画的,具体有的性质以下文所述为准。)

见上,假设 \(AD\) 之间存在格点(在之后称为不合法),于是我们找到任意一点 \(C\) 进行更新。

假设 \(C\) 为不合法,以图为例,在 \(AC\) 上可以取一格点 \(B\),根据三角形定则 \(| \ BD \ |>| \ BC \ |+| \ CD \ |\),则 \(B\) 更优。假设无法在 \(AB\) 和 \(BD\) 上取格点,那么 \(B\) 的取点是合法的,可以得出:

推论 2:对于任意不合法的取点,必然可以在原线段取到更优的合法方案。

那么就有:

推论 2.1:最优方案必然是合法的。

对推论 2.1 的证明:

假设最优方案不合法,根据推论 2,则有更优方案可以更新,与原有条件冲突,由此可得。

以上是一个转折点的情况,那如果有多个转折点呢?

如图,多个转折点的情况是不需要考虑的,见图,由于三角形定则,红色线的长度小于另外两条边之和。换句话说:

推论 3:最优方案只转折一次或零次。

于是我们只要枚举一个点就可以了,如果在整个 \(n\times m\) 的范围枚举,寻找最优方案,但这个时间复杂度显然是不合理的。其实我们只需要枚举线段附近的点就可以,这样复杂度就可以变成 \(\mathcal{O}(n)\)。

代码实现

#define by_wanguan
#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
int t,n,m,y11,y2,y3,g; double dn,dm,nowm,ans,k;
double dis(double a,double b,double x,double y){
  return sqrt((x-a)*(x-a)+(y-b)*(y-b));
}
void solve(){
  k=(double)m/n;//斜率
  if((g=__gcd(n,m))==1)
    {printf("%.15lf\n",dis(0,0,n,m)); return ;}
  dn=n,dm=m;
  for(int i=1;i<n;i++){
    nowm=k*i;
    y11=(int)(nowm),y2=y11+1,y3=y11-1;//x坐标为i时附近的点的y坐标
    if(__gcd(n-i,m-y11)==1&&__gcd(i,y11)==1&&abs(y11-k*i)>1e-10)
    //判断是否合法,abs()是在判断是否为原线段上的点
	  ans=min(ans,dis(i,y11,n,m)+dis(0,0,i,y11));
    if(__gcd(n-i,m-y2)==1&&__gcd(i,y2)==1&&abs(y2-k*i)>1e-10)
      ans=min(ans,dis(i,y2,n,m)+dis(0,0,i,y2));
    if(__gcd(n-i,m-y3)==1&&__gcd(i,y3)==1&&abs(y3-k*i)>1e-10)
      ans=min(ans,dis(i,y3,n,m)+dis(0,0,i,y3));
  }
  printf("%.15lf\n",ans);
}
int main(){
  scanf("%d",&t); while(t--){
  scanf("%d%d",&n,&m);
  ans=1e9;
  solve();
}
} 

喵。

标签:推论,洛谷,gcd,double,题解,格点,ans,P9830,dis
From: https://www.cnblogs.com/wanguan/p/18344028

相关文章

  • P9596 冒泡排序 2 题解
    题目链接。Statement记\(f(A)\)为序列\(A\)的冒泡排序趟数,操作:单点改,全局查\(f(A)\).\(n,m\le5\cdot10^5\),值域1e9.Solution结论:\[Ans=\max_{i\in[1..n]}\left\{\sum_{j\in[1..i]}[A_j>A_i]\right\}\]怎么观察出来啊QAQ证明:对于每个位置\(p\),观察到每趟都......
  • AGC046C 题解
    blog。好菜啊,不会这题,来写个题解/kel。很难直接做,先找一点性质:操作只改变相对顺序,而总数不变。这启示我们记录每个\(0\)前面的极长\(1\)连续段长度。记第\(i(1\lei\leC)\)个\(0\)对应长度为\(a_i\),就存在下面的等价表述:每次操作可以选定\(i,j(1\lei<j\leC)\),......
  • 洛谷-P9574 题解
    思路分析分析样例:==TTBTBTTBTBTTTBTTB->TTBTTBBTTBTTTBTTB->TTBTTBTBBTTTTBTTB->TTBTTBTBBTTTTTBBT----1-----2-----3---4--观察区块2,发现BTTB进行操作后与右边的TB再次构成BTTB,我们发现在这个区块内,可以从左向右不断操作,我们称这种特性为传递性,可......
  • AT_abl_e Replace Digits 题解
    题目传送门前置知识线段树解法需要维护区间信息,考虑使用线段树维护。预处理出\(\overline{xx\dotsx}\),其中\(x\in\{1,2,3,4,5,6,7,8,9\}\),便于区间赋值。然后就是普通的线段树板子了。代码#include<bits/stdc++.h>usingnamespacestd;#definelllonglong#de......
  • AGC027C 题解
    注意到如果可以构造出所有由\(\texttt{A}\)和\(\texttt{B}\)组成的字符串,那么在图上游走的路径必须成环,并且的环上的每一个点都必须同时有一个\(\texttt{A}\)邻居和\(\texttt{B}\)邻居。于是可以考虑把点拆分为入点和出点,相邻两个点为\(\texttt{AA},\texttt{BB}\)的,从......
  • npm下载包时报错 Unexpected token ‘.‘问题解决
    项目场景:项目需要使用node18.12.0以上版本的,但是npm下载显示异常问题描述当通过nvm切换nodejs版本为16以上时,npminstall[package]报错:Unexpectedtoken'.'原因分析:提示:该问题不是npm的问题,也不是nodejs的问题,是nvm-windows的问题我是通过nvm-windows已经更新版本......
  • 洛谷P1223 排队接水
    P1223排队接水题目描述有\(n\)个人在一个水龙头前排队接水,假如每个人接水的时间为\(T_i\),请编程找出这\(n\)个人排队的一种顺序,使得\(n\)个人的平均等待时间最小。输入格式第一行为一个整数\(n\)。第二行\(n\)个整数,第\(i\)个整数\(T_i\)表示第\(i\)个人的......
  • 《数据结构习题解析与实验指导_李冬梅,张琪编著》总结出的大纲
        下面大纲为《数据结构习题解析与实验指导_李冬梅,张琪编著》总结出的大纲,可装13学习下:          ......
  • Codeforces Round 963 (Div. 2) D题解
    CodeforcesRound963D题目描述给定两个正整数n和k以及另一个由n个整数组成的数组a。在一次操作中,可以选择a中大小为k的任意一个子数组,然后将其从数组中删除,而不改变其他元素的顺序。更正式地说,假设(l,r)是对子数组a[l],a[l+1],...,a[r]的操作,使得r-l+1......
  • leetcode200. 岛屿数量C++题解,精美图例和流程图,一题带你弄懂图的dfs遍历算法
    leetcode200.岛屿数量给你一个由‘1’(陆地)和‘0’(水)组成的的二维网格,请你计算网格中岛屿的数量。岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。此外,你可以假设该网格的四条边均被水包围。示例1:输入:grid=[[“1”,“1”,“1”,......