蓝桥杯:矩阵翻硬币(大数开根号)

问题描述
  小明先把硬币摆成了一个 n 行 m 列的矩阵。

  随后,小明对每一个硬币分别进行一次 Q 操作。

  对第x行第y列的硬币进行 Q 操作的定义:将所有第 i*x 行,第 j*y 列的硬币进行翻转。

  其中i和j为任意使操作可行的正整数,行号和列号都是从1开始。

  当小明对所有硬币都进行了一次 Q 操作后,他发现了一个奇迹——所有硬币均为正面朝上。

  小明想知道最开始有多少枚硬币是反面朝上的。于是,他向他的好朋友小M寻求帮助。

  聪明的小M告诉小明,只需要对所有硬币再进行一次Q操作,即可恢复到最开始的状态。然而小明很懒,不愿意照做。于是小明希望你给出他更好的方法。帮他计算出答案。
输入格式
  输入数据包含一行,两个正整数 n m,含义见题目描述。
输出格式
  输出一个正整数,表示最开始有多少枚硬币是反面朝上的。
样例输入
2 3
样例输出
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;
    }
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值