问题描述
小明先把硬币摆成了一个 n 行 m 列的矩阵。
随后,小明对每一个硬币分别进行一次 Q 操作。
对第x行第y列的硬币进行 Q 操作的定义:将所有第 i*x 行,第 j*y 列的硬币进行翻转。
其中i和j为任意使操作可行的正整数,行号和列号都是从1开始。
当小明对所有硬币都进行了一次 Q 操作后,他发现了一个奇迹——所有硬币均为正面朝上。
小明想知道最开始有多少枚硬币是反面朝上的。于是,他向他的好朋友小M寻求帮助。
聪明的小M告诉小明,只需要对所有硬币再进行一次Q操作,即可恢复到最开始的状态。然而小明很懒,不愿意照做。于是小明希望你给出他更好的方法。帮他计算出答案。
随后,小明对每一个硬币分别进行一次 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;
对于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;
}
}