蓝桥杯练习系统 矩阵翻硬币 大数,牛顿迭代法 难度: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);

	}



}

 

你可能感兴趣的:(蓝桥杯)