1. 程式人生 > >藍橋杯:矩陣翻硬幣(大數開根號)

藍橋杯:矩陣翻硬幣(大數開根號)

  對於10%的資料,n、m <= 10^3;
  對於20%的資料,n、m <= 10^7;
  對於40%的資料,n、m <= 10^15;

  對於10%的資料,n、m <= 10^1000(10的1000次方)。

我的思路:他是問翻之前有多少個硬幣是反面朝上的,所以這個反面朝上的硬幣被翻了奇數次才能正面朝上 那麼怎麼才能被翻奇數           次呢? 假設這一行(列)為i行(列),他有多少個因子 就要被翻多少次 如:10=1*10,10*1,2*5,5*2,要這樣被翻四               次,只要因子為奇數個就被翻奇數次,那麼哪些數的因子為奇數個呢?  

          如1=1*1      4=1*4,2*2      9=1*9,3*3 這些數的因子都是奇數個 

          找到這樣的行和列 的交點是不是就是被翻了奇數次呢.  所以我們只要找出列和行分別包括幾個這樣的數 乘積就是反面朝上的個數

          那麼怎麼找?如2開根號等於1.4142...  5開根號等於2.2360...  10開根號等於3.1622.... 發現了什麼規律麼

          是的 它的整數部分就是從1到他包括幾個完全平方數 

                這裡的資料測試 要測試到10的1000次方 所以用大數 來做。

                還是知識儲量不夠,不知道怎麼用大數開根號 所以直接這樣弄的 結果長度超過long的長度後 就開始出錯了 只得了40分


public static void main(String[] args) {
        Scanner s = new Scanner(System.in);
        BigInteger a = sqrt(s.nextBigInteger());
        BigInteger b = sqrt(s.nextBigInteger());
        System.out.println(a.multiply(b));
    }
    public static BigInteger sqrt(BigInteger a){
    	BigInteger x=BigInteger.valueOf((long) (Math.sqrt(a.doubleValue())/1));
    	return x;
    }

我這樣開根還是40分

   public static BigDecimal deal(BigDecimal x){ 
       MathContext mc = new MathContext(1000,RoundingMode.HALF_DOWN);
       x = new BigDecimal(Math.sqrt(x.doubleValue()),mc);  
       x = x.setScale(0, BigDecimal.ROUND_DOWN);  
       return x;  
   }
之後在網上查了一下大神做的 發現大數開根號還這麼複雜閉嘴   又學習到了新技能


import java.util.*;
import java.math.*;

public class 矩陣翻硬幣{ 
    public static void main(String[] args) {
        Scanner s = new Scanner(System.in);
        BigInteger x=sqrt(s.nextBigInteger());
        BigInteger y=sqrt(s.nextBigInteger());
        System.out.println(x.multiply(y));
    }
    public static BigInteger sqrt(BigInteger a){
    	BigInteger w=BigInteger.ZERO;
    	BigInteger r=BigInteger.ZERO;
    	BigInteger num_1=BigInteger.valueOf(10);
    	BigInteger num_2=BigInteger.valueOf(20);
    	if(a==BigInteger.ONE)
    		return BigInteger.ONE;
    	int len=len(a);
    	r=BigInteger.valueOf(Num(a,len--));
    	if(len%2==1)
    		r=r.multiply(num_1).add(BigInteger.valueOf(Num(a,len--)));
    	while(len>=0){
    		int i=0;
    		BigInteger num_i=BigInteger.valueOf(i);
    		while(r.compareTo(w.multiply(num_2).add(num_i).multiply(num_i))>=0)
    			num_i=BigInteger.valueOf(++i);
    		num_i=BigInteger.valueOf(--i);
    		r=r.subtract(w.multiply(num_2).add(num_i).multiply(num_i));
    		w=w.multiply(num_1).add(num_i);
    		if(len>1){
    			r=r.multiply(num_1).add(BigInteger.valueOf(Num(a,len--)));
    			r=r.multiply(num_1).add(BigInteger.valueOf(Num(a,len--)));
    		}
    		else len-=2;
    	}
        return w;
    }
    public static int Num(BigInteger a,int len){
    	BigInteger num=BigInteger.valueOf(10);
    	num=num.pow(len-1);
    	a=a.divide(num);
    	a=a.mod(BigInteger.TEN);//只去一位 多的位數 取模 去掉
    	return a.intValue();
    }
    public static int len(BigInteger a){
    	int len=0;
    	while(a!=BigInteger.ZERO){
    		a=a.divide(BigInteger.TEN);
    		len++;
    	}
    	return len;
    }
}