藍橋杯:矩陣翻硬幣(大數開根號)
阿新 • • 發佈:2019-01-30
對於10%的資料,n、m <= 10^3;
對於20%的資料,n、m <= 10^7;
對於40%的資料,n、m <= 10^15;
對於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;
}
}