您的位置:首页 > 其它

历届试题 矩阵翻硬币(大数开方)

2017-02-20 16:11 225 查看
历届试题 矩阵翻硬币  

时间限制:1.0s   内存限制:256.0MB
    

问题描述

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

 这个题最先是想着通过模拟翻硬币的那个过程做的,但是提交后数据量非常大只过了10%的数据,然后打印出翻硬币的情况,从中发现了规律。

最终,归结为n开方数*m的开方数即为最终输出的结果。燃鹅,n和m都是非常的数,这就涉及到大数开方的算法。

模拟翻硬币的过程代码:

import java.util.Scanner;

public class 矩阵翻硬币 {

public static void main(String[] args) {

Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
int m=sc.nextInt();

int count=getFan(n+1,m+1);
System.out.println(count);
}
private static int getFan(int n,int m) {

int[][] data=new int
[m];

for (int i = 1; i < n+1; i++) {
for (int j = 1; j < m+1; j++) {
int x=i,y=j;
for (int k = 1; k*x < n; k++) {
for (int h = 1; h*y < m ; h++) {
if(data[k*x][h*y]==0)
data[k*x][h*y]=1;
else
data[k*x][h*y]=0;
}
}
}
}
int count=0;
for (int i = 1; i < n; i++) {
for (int j = 1; j < m; j++) {
System.out.print(data[i][j]+",");
if(data[i][j]==1)
count++;
}
System.out.println();
}
return count;
}
}

找到规律后用n开方*m开方:

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

public class 大数开方2 {

public static void main(String[] args) {

Scanner sc=new Scanner(System.in);

BigInteger n=sc.nextBigInteger();
BigInteger m=sc.nextBigInteger();

System.out.println(sqrt(n).multiply(sqrt(m)));

}

private static BigInteger sqrt(BigInteger n) {
BigInteger a;
BigInteger b;

a=BigInteger.TEN.pow((int)n.toString().length()/2);
b=n.divide(a);

while(!(a.equals(b)||a.equals(b.add(new BigInteger("-1")))||b.equals(a.add(new BigInteger("-1"))))){
a=a.add(b).divide(new BigInteger("2"));//a=(a+b)/2
b=n.divide(a);
}

if (a.equals(b.add(new BigInteger("-1")))) {
return a;
}
return b;
}
}

大数开方的算法:
import java.math.BigInteger;
import java.util.Scanner;

public class 大数开方3 {
public static BigInteger getSqrt(BigInteger n){
BigInteger a,b;
BigInteger cs=new BigInteger("2");
int len=n.toString().length();
a=BigInteger.TEN.pow(len/2);
b=n.divide(a);
int k=1;
while(k==1){
if(a.equals(b)||a.equals(BigInteger.ONE.add(b))||b.equals(BigInteger.ONE.add(a))){
k=0;
}else{
a=a.add(b).divide(cs);
b=n.divide(a);
}
}
return a;
}
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc=new Scanner(System.in);
for (int i = 1; i < 20; i++) {
BigInteger n=BigInteger.valueOf(i);
System.out.println(i+"开方为:"+getSqrt(n));
}
//BigInteger n=sc.nextBigInteger();
//System.out.println(getSqrt(n));
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: