• Java中利用BigInteger类进行大数开方


      在Java中有时会用到大数据,基本数据类型的存储范围已经不能满足要求了,如要对10的1000次方的这样一个数据规模的数进行开方运算,很明显不能直接用Math.sqrt()来进行计算,因为已经溢出了。 

      牛顿迭代法(Newton's method)又称为牛顿-拉夫逊方法(Newton-Raphson method),它是牛顿在17世纪提出的一种在实数域和复数域上*似求解方程的方法。多数方程不存在求根公式,因此求精确根非常困难,甚至不可能,从而寻找方程的*似根就显得特别重要。方法使用函数f(x)的泰勒级数的前面几项来寻找方程f(x) = 0的根。牛顿迭代法是求方程根的重要方法之一,其最大优点是在方程f(x) = 0的单根附*具有*方收敛,而且该法还可以用来求方程的重根、复根。另外该方法广泛用于计算机编程中。

    设r是f(x) = 0的根,选取x0作为r初始*似值,过点(x0,f(x0))做曲线y = f(x)的切线L,L的方程为y = f(x0)+f'(x0)(x-x0),求出L与x轴交点的横坐标 x1 = x0-f(x0)/f'(x0),称x1为r的一次*似值。

      下面以蓝桥杯的一个题为例:

    问题描述
      小明先把硬币摆成了一个 n 行 m 列的矩阵。

      随后,小明对每一个硬币分别进行一次 Q 操作。

      对第x行第y列的硬币进行 Q 操作的定义:将所有第 i*x 行,第 j*y 列的硬币进行翻转。

      其中i和j为任意使操作可行的正整数,行号和列号都是从1开始。

      当小明对所有硬币都进行了一次 Q 操作后,他发现了一个奇迹——所有硬币均为正面朝上。

      小明想知道最开始有多少枚硬币是反面朝上的。于是,他向他的好朋友小M寻求帮助。

      聪明的小M告诉小明,只需要对所有硬币再进行一次Q操作,即可恢复到最开始的状态。
    然而小明很懒,不愿意照做。于是小明希望你给出他更好的方法。帮他计算出答案。
    输入格式
      输入数据包含一行,两个正整数 n m,含义见题目描述。
    输出格式
      输出一个正整数,表示最开始有多少枚硬币是反面朝上的。
    样例输入
    2 3
    样例输出
    1
    数据规模和约定
      对于10%的数据,n、m <= 10^3;
      对于20%的数据,n、m <= 10^7;
      对于40%的数据,n、m <= 10^15;
      对于10%的数据,n、m <= 10^1000(10的1000次方)。
      利用牛顿迭代法可以求解,代码如下:
     

    import java.math.BigDecimal;
    import java.math.BigInteger;
    import java.util.Scanner;

    public class fz {

    public static void main(String[] args) {


    Scanner cin =new Scanner(System.in);

    //for(int i=1;i<100;i++){
    // BigInteger n=cin.nextBigInteger();
    // System.out.println("......"+myBigNumSqrt(n));}


    BigInteger n=cin.nextBigInteger();
    BigInteger m=cin.nextBigInteger();
    BigInteger tem=myBigNumSqrt(n).multiply(myBigNumSqrt(m));
    System.out.println(tem);

    }

    //大数开方
    public static BigInteger myBigNumSqrt(BigInteger xx)
    {
    BigDecimal x=new BigDecimal(xx);
    BigDecimal n1=BigDecimal.ONE;
    BigDecimal ans=BigDecimal.ZERO;
    //int i=1;
    while((n1.multiply(n1).subtract(x)).abs().compareTo(BigDecimal.valueOf(0.001))==1)
    {
    //System.out.println(i+"..."+n1);
    //i++;
    BigDecimal s1=x.divide(n1,2000,BigDecimal.ROUND_HALF_UP);
    BigDecimal s2=n1.add(s1);
    n1=s2.divide(BigDecimal.valueOf(2),2000,BigDecimal.ROUND_HALF_UP);

    }
    ans=n1;
    //System.out.println(ans);
    BigInteger rt =new BigInteger(ans.toString().split("\.")[0]);
    return rt;
    }
    }

    输出实例:

  • 相关阅读:
    cf1100 F. Ivan and Burgers
    cf 1033 D. Divisors
    LeetCode 17. 电话号码的字母组合
    LeetCode 491. 递增的子序列
    LeetCode 459.重复的子字符串
    LeetCode 504. 七进制数
    LeetCode 3.无重复字符的最长子串
    LeetCode 16.06. 最小差
    LeetCode 77. 组合
    LeetCode 611. 有效三角形个数
  • 原文地址:https://www.cnblogs.com/yhpbook/p/6675834.html
Copyright © 2020-2023  润新知