zoukankan      html  css  js  c++  java
  • 【BZOJ2712】[Violet 2] 棒球(类欧几里得算法)

    点此看题面

    大致题意: 给定分数(frac pq)四舍五入到第(n)位的值,求(q)的最小值。

    前言

    可以先去看看【BZOJ2187】fraction,和这题几乎完全一样。

    然而在细节上却又有些不同,导致我(WA)了一发又一发。。。

    类欧几里得算法

    首先考虑我们把题目中给定的小数转化为分数,即求出(a,b,c,d)满足(frac ablefrac pq<frac cd)

    然后具体做法不说了,上面那题都有。

    唯一要注意的是,这题中有一侧是可以取等的,且我们取倒数的时候取等的方向会改变。

    代码

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define LL long long
    #define swap(x,y) (x^=y^=x^=y)
    using namespace std;
    int n;LL v,tn;
    I void read(LL& x)
    {
    	char c;W((c=getchar())^'.');x=0;W(isdigit(c=getchar())) x=(x<<3)+(x<<1)+(c&15);
    }
    I LL gcd(Con LL& x,Con LL& y) {return y?gcd(y,x%y):x;}
    I void Get(Con LL& a,Con LL& b,Con LL& c,Con LL& d,LL& x,LL& y,CI op)//类欧几里得算法,op表示取等方向
    {
    	LL Mn=op?a/b+1:(a-1)/b+1,Mx=op?c/d:(c-1)/d;if(Mn<=Mx) return (void)(x=Mn,y=1);//根据op决定能取的整数的上下界
    	if(!a) return (void)(x=1,y=d/c+1);//a=0
    	a<b?(Get(d,c,b,a,x,y,op^1),swap(x,y)):(Get(a%b,b,c-(a/b)*d,d,x,y,op),x+=y*(a/b));//a<b;a≥b
    }
    int main()
    {
    	RI i;LL a,b,c,d,g,x,y;W(~scanf("%d",&n))
    	{
    		for(read(v),tn=i=1;i<=n+1;++i) tn*=10;//读入小数部分,同时计算10的幂
    		g=gcd(a=max(v*10-5,0LL),b=tn),a/=g,b/=g,g=gcd(c=v*10+5,d=tn),c/=g,d/=g;//转化为分数,注意下界不能为负
    		Get(a,b,c,d,x,y,0),printf("%lld
    ",y);//求答案,输出分母
    	}return 0;
    }
    
  • 相关阅读:
    jq insertBefore 的返回值
    微信公众号-定位之地址逆解析&导航
    微信JS-SDK
    Vue
    ES6-函数的扩展
    ES6-数组的扩展
    JSP
    JS
    HTML+CSS
    jdbc操作数据库
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/BZOJ2712.html
Copyright © 2011-2022 走看看