UPC Participate in E-sports(参加电子竞技)(Biginteger的平方根:二分或牛顿迭代法)

Jessie and Justin want to participate in e-sports. E-sports contain many games, but they don't know which one to choose, so they use a way to make decisions.

Je和Ju想去参加电子竞技,电竞有很多项目,但是他们不知道选哪一个,所以他们用一种方式去决策。
           They have several boxes of candies, and there are i candies in the i^th box, each candy is wrapped in a piece of candy paper. Jessie opens the candy boxes in turn from the first box. Every time a box is opened, Jessie will take out all the candies inside, finish it, and hand all the candy papers to Justin.

他们有几个糖果盒,在第i个糖果盒内有i个糖,每一个糖都由糖果纸包裹着,Je从第一个糖果盒开始依次打开糖果盒,每一回糖果盒被打开,Je都会拿出里面的所有糖,吃光它,并把糖纸都给Ju.

When Jessie takes out the candies in the N^th box and hasn't eaten yet, if the amount of candies in Jessie's hand and the amount of candy papers in Justin's hand are both perfect square numbers, they will choose Arena of Valor. If only the amount of candies in Jessie's hand is a perfect square number, they will choose Hearth Stone. If only the amount of candy papers in Justin's hand is a perfect square number, they will choose Clash Royale. Otherwise they will choose League of Legends.Now tell you the value of N, please judge which game they will choose.

当Je拿出第N个盒子里的糖果时,他还没来得及吃。如果Je手里的糖果数和Ju手里的糖果纸数都是一个完全平方数,他们会选王者荣耀,如果只有je手里的糖果数才是一个平方数,那么他们选炉石传说,如果只有Ju手里的糖果纸数才是一个平方数,他们会选皇室战争,否则就选英雄联盟。现在告诉你N的数值,请判断他们会选哪款游戏。

输入

The first line contains an integer T(1≤T≤800), which is the number of test cases. 
Each test case contains one line with a single integer: N(1≤N≤10^200).

输出

For each test case, output one line containing the answer.

根据题意,Je还没有吃第N个盒子里的糖果,其他被吞了,且糖果纸都给了Ju,所以他手里的糖果数是N个,而Ju手中的糖果纸数是1...n-1的自然数序列和。那么主要任务是判断n和(n-1)*n/2是不是完全平方数。数据范围是1~10^200,很明显不是一般的C++数据类型就可以承受得了的,所以考虑使用Java封装的Biginteger和Bigdecimal类型。

然而Java没有封装的BigInteger的平方根函数,所以必须自己想出一个办法解决这个问题。我们都知道二分可以求函数或者方程的根,那么相应的,a平方根就是(x^2-a=0)这个方程的解,所以只要用二分法解这个方程就可以求得平方根。

import java.util.*;
import java.math.*;
public class Main
{
    public static boolean binary(BigInteger left,BigInteger right,BigInteger n)//二分函数
    {
        BigInteger cons2=BigInteger.valueOf(1);
        BigInteger cons=BigInteger.valueOf(2);
        while(left.compareTo(right)<=0)
        {
            BigInteger mid=(left.add(right)).divide(cons);
            BigInteger tmp=mid.multiply(mid);
            if(tmp.compareTo(n)==0)
            {
                return true;
            }
            else if(tmp.compareTo(n)>0)
            {
                right=mid.subtract(cons2);
            }
            else
            {
                left=mid.add(cons2);
            }
 
        }
        return false;
    }
    public static void main(String args[])
    {
        Scanner cin=new Scanner(System.in);
        int t;
        t=cin.nextInt();
        BigInteger cons6=BigInteger.valueOf(1);
        BigInteger cons5=BigInteger.valueOf(2);
        for(int i=1;i<=t;i++)
        {
            BigInteger n=cin.nextBigInteger();
            BigInteger left=BigInteger.valueOf(1),right=n;
            Boolean sign=false,sign2=false;
            if(binary(left, right, n)==true)
                sign=true;
            BigInteger tmp33=(n.multiply(n.subtract(cons6))).divide(cons5);
            if(n.compareTo(cons6)==0||n.compareTo(cons5)==0)
                sign2=true;
            else
                if(binary(left,tmp33,tmp33)==true)
                    sign2=true; 
            //System.out.println(sign+" "+sign2);
            if(sign&&sign2)
            {
                System.out.println("Arena of Valor");
            }
            else if(sign==false&&sign2==true)
            {  
                System.out.println("Clash Royale");
            }
            else if(sign==true&&sign2==false)
            {
                System.out.println("Hearth Stone");
            }
            else
                System.out.println("League of Legends");
        }
        cin.close();
    }
}

当然,还有一种不推荐的办法是牛顿迭代法,在这个题里测试的结果是会MLE+TLE,不过作为一种好用的办法可以多多学习一下。

何谓牛顿迭代法?简而言之就是求函数某点切线,再求得本切线与x轴交的横坐标,再代入原式,从这个点继续作切线,如此往复,最终可以逼近答案。(仅仅讨论平方根,实际上这个可以求N次方根)

上面有说,解一个实数a的平方根的过程就是在解x^{2}-a=0,同样也就是在找 f(x)=x^2-a这个函数的零点。

 

  1. 那么假定函数上一个点为(x0,f(x0)),从这个点作切线,根据点斜式可知其方程:y-f(x0)=f'(x0)(x-x0)
  2. 下一步解出它在x轴上的交点,即当y=0时,x=\frac{x0*f'(x0)-f(x0)}{f'(x0)}
  3. 代入f(x)的表达式,x=\frac{1}{2}*x0+\frac{a}{2x0},这就是主要的表达式依据。因为接下来的所有过程都是重复这个。
import java.util.*;
import java.math.*;
import java.text.*;
public class Main
{
    public static BigInteger SquareRoot(BigInteger parameter)
    {
        函数表达式f(x)=x^2-a
        BigDecimal a=new BigDecimal(parameter);这是常数a
        BigDecimal x=BigDecimal.ONE;这是x0,假如它是1
        while((x.multiply(x).subtract(a)).abs().compareTo(BigDecimal.valueOf(0.0001))>0)
        //当|x^2-a|>0.0001,也就是求得的平方根的平方与原数的差距不能大于这个数,收敛半径为1e-4
        {
            BigDecimal tmp1=a.divide(x,2000,BigDecimal.ROUND_HALF_UP);
            //原文主要表达式的x/a部分
            BigDecimal tmp2=tmp1.add(x);
            //主要表达式的x+x/a部分
            x=tmp2.divide(BigDecimal.valueOf(2),2000,BigDecimal.ROUND_HALF_UP);
            //主要表达式:(1/2)*x+x/(2a)
        }
        BigInteger ans=x.toBigInteger();
        return ans;
    }
    public static void main(String args[])
    {
        Scanner cin=new Scanner(System.in);
        int t=cin.nextInt();
        for(int i=1;i<=t;i++)
        {
            BigInteger n=cin.nextBigInteger();
            BigInteger SumN=n.multiply(n.subtract(BigInteger.ONE)).divide(BigInteger.valueOf(2));
            BigInteger root1=SquareRoot(n),root2=SquareRoot(SumN);
            boolean sign1=false,sign2=false;
            if(root1.multiply(root1).compareTo(n)==0)
                sign1=true;
            if(root2.multiply(root2).compareTo(SumN)==0)
                sign2=true;
            if(sign1&&sign2)
                System.out.println("Arena of Valor");
            else if(sign1&&!sign2)
                System.out.println("Hearth Stone");
            else if(!sign1&&sign2)
                System.out.println("Clash Royale");
            else
                System.out.println("League of Legends");
        }
        cin.close();
    }
}

 

安装Docker安装插件,可以按照以下步骤进行操作: 1. 首先,安装Docker。可以按照官方文档提供的步骤进行安装,或者使用适合您操作系统的包管理器进行安装。 2. 安装Docker Compose插件。可以使用以下方法安装: 2.1 下载指定版本的docker-compose文件: curl -L https://github.com/docker/compose/releases/download/1.21.2/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose 2.2 赋予docker-compose文件执行权限: chmod +x /usr/local/bin/docker-compose 2.3 验证安装是否成功: docker-compose --version 3. 在安装插件之前,可以测试端口是否已被占用,以避免编排过程中出错。可以使用以下命令安装netstat并查看端口号是否被占用: yum -y install net-tools netstat -npl | grep 3306 现在,您已经安装Docker安装Docker Compose插件,可以继续进行其他操作,例如上传docker-compose.yml文件到服务器,并在服务器上安装MySQL容器。可以参考Docker的官方文档或其他资源来了解如何使用DockerDocker Compose进行容器的安装和配置。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [Docker安装docker-compose插件](https://blog.youkuaiyun.com/qq_50661854/article/details/124453329)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *3* [Docker安装MySQL docker安装mysql 完整详细教程](https://blog.youkuaiyun.com/qq_40739917/article/details/130891879)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值