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 表示 反面)
*/
矩阵翻硬币.java
最新推荐文章于 2022-03-20 17:43:35 发布