蓝桥杯练习系统 矩阵翻硬币 大数,牛顿迭代法 难度:2

http://lx.lanqiao.org/problem.page?gpid=T126

明显,对于一个格子(i,j),设f(i)为i的约数个数,则(i,j)的翻转次数为(f(i)-1)*(f(j)-1)+1,

而只有翻转次数为奇数,也就是f(i),f(j)都为奇数的格子开始才是反面,

又因为f(i)为奇数当且仅当i为完全平方数,所以只需统计n,m中各有多少个完全平方数,然后相乘即可,

也就是sqrt(n)*sqrt(m),

但是因为n,m是大数,必须要用大数方法解决,这里采用了java的BigInteger类,用牛顿迭代法逼近整数解.

牛顿迭代法就是设y=f(x),设r是f(x)=0的解,x0是一个备用解,则y约等于f(x0)+f'(x0)*(x-x0),在已知y,f(x)的情况下,可从中解得x作为一级解,然后再填入该公式解出二级解,一直这么重复,解会越来越精确,可以证明如果f(x)是连续的,并且零点附近是孤立的,x会逐渐收敛在解r的附近

对于这道题,设y=x^2,则y'=2*x,每次迭代中x=(y+x0*x0)/2/x0

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


public class Main {
	static BigInteger mysqrt(BigInteger n){
		BigInteger two=BigInteger.valueOf(2);
		BigInteger l=BigInteger.ONE,r=(n.divide(l.multiply(two))).add(l.divide(two));
		while(!l.equals(r)){
			l=r;
			r=(n.divide(l.multiply(two))).add(l.divide(two));
			if(l.subtract(r).abs().equals(BigInteger.ONE))break;
		}
		while(l.multiply(l).compareTo(n)>0){
			l=l.subtract(BigInteger.ONE);
		}
		while(l.add(BigInteger.ONE).multiply(l.add(BigInteger.ONE)).compareTo(n)<=0){
			l=l.add(BigInteger.ONE);
		}
		return l;
	}
	public static void main(String[] args) {
		BigInteger m,n;
		Scanner scanner =new Scanner(System.in);
		m=scanner.nextBigInteger();
		n=scanner.nextBigInteger();
		BigInteger nn=mysqrt(n);
		BigInteger mm=mysqrt(m);
		BigInteger ans = nn.multiply(mm);
		System.out.println(ans);
	}

}

 

posted @ 2015-04-06 16:14  雪溯  阅读(423)  评论(2编辑  收藏  举报