蓝桥杯 矩阵翻硬币

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


解析:

1.每个硬币被翻转的次数为其横坐标的约数个数 * 其纵坐标的约数个数。

2.如果一个硬币被翻转奇数次,说明其初始状态为反面朝上。

3.因为奇数 * 奇数 = 奇数 , 则需要找出约数为奇数的坐标。

4.如果一个数的约数个数为奇数,说明它是一个完全平方数。

5.在m的范围内,完全平方数的个数为sqrt(m)个。

6.在矩阵中,有sqrt(a)行是奇数,sqrt(b)列是奇数。

7.则所有正面朝上的硬币个数为sqrt(a) * sqrt(b)。

代码:

import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Scanner input = new Scanner(System.in);
		String strA = input.next();
		String strB = input.next();
		char[] a = strA.toCharArray();
		char[] b = strB.toCharArray();
		read(multiply(sqrt(a),sqrt(b)));
		input.close();
	}

	// 大数相乘
	private static int[] multiply(char[] a, char[] b) {
		int[] c = new int[a.length + b.length];
		for (int i = a.length - 1; i >= 0; i--) {
			for (int j = b.length - 1; j >= 0; j--) {
				c[(a.length - 1) + (b.length - 1) - (i + j)] += (a[i] - '0') * (b[j] - '0');
			}
		}
		for (int i = 0; i < c.length - 1; i++) {
			c[i + 1] += c[i] / 10;
			c[i] = c[i] % 10;
		}
		int i;
		for(i = c.length-1;i>=0 && c[i] == 0;i--);
		int []d = new int[i+1];
		int j = 0;
		for(;i >= 0;i--)
			d[j++] = c[i];
		return d;
	}

	// 大数开方
	private static char[] sqrt(char a[]) {
		int len = (a.length & 1) == 1 ? a.length / 2 + 1 : a.length / 2;
		char[] c = new char[len];
		
		for(int i = 0;i < c.length;i++)
			c[i] = '0';
		
		for (int i = 0; i < len; i++) {
			for (char j = '0'; j <= '9'; j++) {
				c[i] = j;
				int[] tmp = multiply(c, c);
				int t = compare(tmp,a);
				if (t == 0)
					break;
				if (t == 1) {
					c[i] -= 1;
					break;
				}
			}
		}
		return c;
	}

	// 大数比较
	private static int compare(int a[], char b[]) {
		if (a.length < b.length)
			return -1;
		if (a.length > b.length)
			return 1;
		for (int i = 0; i < a.length; i++) {
			if (a[i] == (int) (b[i] - '0'))
				continue;
			if (a[i] > (int) (b[i] - '0'))
				return 1;
			else
				return -1;
		}
		return 0;
	}

	// 输出大数
	private static void read(int [] c) {
		for (int i = 0; i < c.length; i++)
			System.out.print(c[i]);
		System.out.println();
	}
}

猜你喜欢

转载自blog.csdn.net/qq_29215513/article/details/79370265