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