题目
https://vjudge.net/problem/51Nod-1166
思路
用更快的牛顿迭代法。把问题转化为求x^2 -n=0的根,假设解为x0,当前解为x 且 x^2 - n>0,在(x,x^2 - n)处作切线,与x轴交点横坐标为新的x,然后迭代即可,比二分法快
牛顿迭代法(Newton’s method)又称为牛顿-拉夫逊(拉弗森)方法(Newton-Raphson method),它是牛顿在17世纪提出的一种在实数域和复数域上近似求解方程的方法。公式为:(x+a/x)/2
这种方法可以很有效地求出根号a的近似值:例如,我想求根号2等于多少。使用牛顿迭代法后这个值很快就趋近于根号2了:
(4 + 2 / 4) / 2 = 2.25
(2.25 + 2 / 2.25) / 2 = 1.56944…
(1.56944… + 2/1.56944…) / 2 = 1.42189…
(1.42189… + 2/1.42189…) / 2 = 1.41423…
代码
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.math.BigInteger;
import java.util.StringTokenizer;
public class Main {
/**
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
String a = _07Reader.next();
BigInteger N = new BigInteger(a);
//下面的if语句不晓得干什么的,不带上会超时
//如果输入的是偶数位的数,例如16
if (N.toString().length() % 2 == 0) {
//截取这两位数
a = a.substring(0, N.toString().length()/2 + 1);
}else {
a = a.substring(0, (1+N.toString().length())/2);
}
BigInteger x = new BigInteger(a);
BigInteger two = new BigInteger("2");
//考虑输入是1的情况
if (a == "1") {
System.out.println(1);
}else {
//N - x^2 < 0的条件
while (N.compareTo(x.multiply(x)) < 0) {
//导入公式(x+a/x)/2
x = x.add(N.divide(x)).divide(two);
}
System.out.println(x);
}
}
}
class _07Reader {
static BufferedReader br = new BufferedReader(new InputStreamReader(
System.in));
static StringTokenizer tokenizer = new StringTokenizer("");
static String next() throws Exception {
while (!tokenizer.hasMoreTokens()) {
tokenizer = new StringTokenizer(br.readLine());
}
return tokenizer.nextToken();
}
static String nextLine() throws Exception {
return br.readLine();
}
static int nextInt() throws Exception {
return Integer.parseInt(next());
}
}
拓展
这个是求BigDecimal平方根的方法,遇到这样的题再说吧,先放着…
JAVA BigDecimal使用牛顿迭代法计算平方根