zoukankan      html  css  js  c++  java
  • 3736. 【NOI2014模拟7.11】数学题(math)

    Description

    给定两个向量 \(\mathbf{a}=\left(x_{1}, y_{1}\right), \mathbf{b}=\left(x_{2}, y_{2}\right)\) 。求出一对整数 \(\lambda_{1}, \lambda_{2}\), 使得 \(\left|\lambda_{1} \mathbf{a}+\lambda_{2} \mathbf{b}\right|\) 最小 \((|\mathrm{v}|\) 表示向量 \(\mathrm{v}\) 的长度 \()\) 。要求 \(\lambda_{1}, \lambda_{2}\) 不同时为 0 。

    Solution

    引理 1:当两向量夹角 \(\theta>\frac{\pi}{3}\),即 \(\cos \theta<\frac{1}{2}\) 时,答案为\(\min(|\vec{a}|,|\vec{b}|)^2\)

    证明:

    \(p=|a|,q=|b|\),不妨设 \(p<q\),则

    \(\begin{aligned}|\vec{a}x+\vec{b}y|&=\sqrt{(px)^2+(qy)^2-2pxqy\cos \theta}\\&\ge\sqrt{|px|^2+|qy|^2-2|px||qy|\cos \theta}\\&\ge\sqrt{|px|^2+|qy|^2-|px||qy|}\\&\ge\sqrt{(|px|-|qy|)^2+|px||qy|}\end{aligned}\)

    \(x=0\),则 \(y\not=0\)\((|px|-|qy|)^2=|qy|^2\ge q^2\ge p^2\)

    \(y=0\),则 \(x\not=0\)\((|px|-|qy|)^2=|px|^2\ge p^2\)

    否则 \(|px||qy|\ge |p||q|\ge p^2\)

    引理 2:\((a,b)\) 所对应的答案,和 \((a,b+ka)\) 一致,其中 \(k\) 为整数。

    证明:

    \(|ax+by|\) 为所求答案,则 \(|a(x-ky)+(b+ka)y|\) 也是,即 \((x,y)\) 对应着答案 \((x-ky,y)\)。并且若 \((x,y)\not=(0,0)\),则 \((x-ka,y)\not=(0,0)\)。同理可证相反方向。

    根据这两个引理,那么使用欧几里得算法就是显而易见的。

    通过引理 2 的变换,将两向量的夹角满足引理 1 的条件,就是我们的目标。

    但我们还要求出在引理 2 中提到的 \(k\)。这里我们规定 \(|\vec{a}|\le|\vec{b}|\)

    \(c=ka\)

    如果 \(k<1\),那么可以证得 \(\vec{b}=\vec{b}-\vec{a}\) 是符合要求的变换。

    如果 \(k>1\),那么将 \(k\) 下取整,即可保证 \(ka\le c\),那么 \(\vec{b}=\vec{b}-\vec{a}k\)即可。

    Code

    #include<cmath>
    #include<cstdio>
    #include<algorithm>
    #define ll long long
    #define db double
    using namespace std;
    struct node
    {
        ll x,y;
        db len() {return sqrt((db)x*x+y*y);}
        int operator*(node b) {return x*b.x+y*b.y;}
        node operator*(ll b) {return (node){x*b,y*b};}
        node operator+(node b) {return (node){x+b.x,y+b.y};}
        node operator-(node b) {return (node){x-b.x,y-b.y};}
    }x,y,z;
    db calc_cos(node a,node b) {return (db)(a*b)/(a.len()*b.len());}
    int main()
    {
        freopen("math.in","r",stdin);
        freopen("math.out","w",stdout);
        while (scanf("%lld%lld%lld%lld",&x.x,&x.y,&y.x,&y.y)!=EOF)
        {
            if (x.x*y.y==x.y*y.x)
            {
                printf("%d\n",0);
                continue;
            }
            if (x*x>y*y) swap(x,y);
            if (x*y<0) y=y*-1;
            db co=calc_cos(x,y);
            while (co>0.5)
            {
                if (x*x>y*y) swap(x,y);
                if (x*y<0) y=y*-1;
                if (x*y/(x*x)<=1) y=y-x;
                else
                {
                    z=x*(x*y/(x*x));
                    y=y-z;
                }
                co=calc_cos(x,y);
            }
            printf("%lld\n",min(x*x,y*y));
        }
        return 0;
    }
    
  • 相关阅读:
    git提交代码五部曲
    菜单树jstree.js插件几个主要事件汇总
    创维电视加mac过滤后连不了wifi问题(路由器为TP-link)
    Mysql和Navicat for MySQL本地运行.sql文件
    MySQL下载与安装
    js一个区域拖拽到另一个区域,拖拽后还可以排序。知识点:js插件Jquery-UI:拖拽组件draggable,放置组件droppable,排序组件sortable
    echarts基本应用-更改坐标轴文字样式、轴名称、轴刻度、轴线、轴网格、曲线(折线图)、柱体上面显示值(柱状图),鼠标悬浮提示
    boostrap的时间插件daterangepicker.js之单日期,精确到秒
    echarts用法之点击事件(圆柱体例子)
    注册界面和功能
  • 原文地址:https://www.cnblogs.com/Livingston/p/15799838.html
Copyright © 2011-2022 走看看