矩阵翻硬币.java

package A类有价值的回顾的;

import java.math.BigInteger;
import java.util.Arrays;
import java.util.Scanner;

public class 矩阵翻硬币 {


    private static BigInteger MaxSqrt(String s){

        BigInteger b = new BigInteger(s);
        int len = s.length();
        int len2;

        if(len%2 == 0) len2 = len/2;
        else  len2 = len/2 + 1;//这是一种规律,被开方的数 的长度是 开方以后的数 的两倍,这就是剪枝的思想

        char[] arr = new char[len2];
        Arrays.fill(arr, '0');//开方数初始化为0,为什么?
        for(int i=0;i<len2;i++){
                     //本来就是‘0’   傻逼,当然可以取 9
            for(char num = '1';num <= '9';num++){

                arr[i] = num;//字符数组先转换成字符串,再转换成大数
                String s2 =String.valueOf(arr);
                //System.out.println(s2);
                BigInteger b2 = new BigInteger(s2);
                BigInteger bb = b2.multiply(b2);
                if(bb.compareTo(b) == 1){//突然找到一个比原先的b大的bb,就让b2--,并退出循环
                //bb.compareTo(b2) == 1 怎么可能是跟b2比,当然是跟目标大数比,TMD什么时候才能消灭这种破事
                    arr[i]--;//对于每一位来说,找到比目标大数小的数中最大的即可,即找到比目标大数大的数减一
                    break;//只是跳出此前的一层循环,再进行的是下一位的选择
                }
            }
        }

        String s3 = String.valueOf(arr);
        return new BigInteger(s3);//可以将字符串转换成大数,因为本身大数就是用字符串储存的

    }

    public static void main(String[] args){

        Scanner sc = new Scanner(System.in);
        String ns = sc.next();//n行
        String ms = sc.next();//m列

        BigInteger ni = MaxSqrt(ns);
        BigInteger mi = MaxSqrt(ms);
        //System.out.println(ni);
        //System.out.println(mi);
        BigInteger b = ni.multiply(mi);//BigInteger b = ni.multiply(ni);
        System.out.println(b);         //也就是说在n行下ni行可以开方,在m列下有mi列可以开方     

    }
}



/*
 *  对第x行第y列的硬币进行 Q 操作的定义:将所有第 i*x 行,第 j*y 列的硬币进行翻转。 其中i和j为任意使操作可行的正整数,行号和列号都是从1开始。
 * 这句话一定要理解好啊,题目都没理解好,你做个屁啊      一次Q操作中,i有多种选择时当然所有的都执行一遍  
 * 这里有相互关系的两者,x 与 i*x ,这就是两种思考的角度, 真是,这种题就是对多种思维方式的组合,遗漏任何细节都会寸步难行
 * 再一个,能对 第 i*x 行,第 j*y 列  所在的点产生影响的是 i*x约数——x行 和 j*y约数——y列  的焦点,如果x有奇数种,y也有奇数种,那么组合的坐标就会有奇数种,这就是原先的反面
 * 这就转换成找 行列坐标的约数都为奇数种 的点
 * 再一个,只要能开方,那么约数的个数就是奇数,这就变成了大数求开方
 * 接下来,对于大数开方,先确定位数然后遍历求解更好
 * 最后,如果一个一个遍历对于大数来说是不行的,可以一位一位的遍历,每一位都找一个 可行中最大的 
 * 再一个,对于 n,m,其范围内 [ 1 , n ] , [ 1 , m ] 完全平方数的个数为 sqrt(n), sqrt(m)个,比如说n=16,[1,n]中,1*1,2*2,3*3,4*4共有sqrt(n)个
 * 对于不能开方的m、n,只要找到小于m的最大的能开方数即可
 */




/*
 * 题目:

     小明先把硬币摆成了一个 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次方)。

     题目的意思很清楚。小M提供了一种算法,这里演示一下 n = 2, m = 3矩阵的翻硬币过程(1 表示 正面, 0 表示 反面)

 */



  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值