矩阵翻硬币

 这是蓝桥杯的一道练习题,题目如下:

问题描述
  小明先把硬币摆成了一个 n 行 m 列的矩阵。
  随后,小明对每一个硬币分别进行一次 Q 操作。
  对第x行第y列的硬币进行 Q 操作的定义:将所有第 ix 行,第 jy 列的硬币进行翻转。
  其中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次方)。

 

 思路:

  对于坐标为(x,y)的硬币来说,当被翻转的次数为奇数时,它的朝向会被改变。被翻转的次数等于x的约数个数乘以y的约数个数。而翻转次数为奇数的充要条件时x和y的约数都是奇数,即x,y都是完全平方数。
  对于矩阵nm,其中横纵坐标皆为完全平方数的硬币个数为:sqrt(n)sqrt(m)。
- - -

  这道题的另一个难点是求超大整数的平方根。网上一个比较经典的算法是:
  对于一个整数num,其位数为n,若n为奇数,则其平方根的位数length = (n+1)/2;若n为偶数,则其平方根的位数length = n/2。 我们从1000...000(有length-1个0)的最高位开始,若这个数的平方小于num,则将当前位的数值加1;若这个数的平方大于num,则将当前位的数值减1,并开始分析下一位。
- - -

  计算平方时,免不了需要自己实现大数的乘法。同样是参考网上的例子,算法如下:
  首先使用char数组存储整数,用int类型的数组ret暂时保存结果,整数的低位存在数组的低位。对输入的两个数组x和y,将其每一位x[i]和y[j]分别相乘,将数值添加到ret[i+y]中。
  现在,ret的的每个元素可能是大于10的,对于每一个元素的数值,我们将个位数保存,将十位数进位。
  ret[i+1] += ret[i] / 10;  
  ret[i] = ret[i] * 10;
  最后,将int类型的数组转化为char类型并返回。
  主要算法就是这些。

 代码:

import java.util.Scanner;public class Main {public static void main(String[] args){Scanner scan = new Scanner(System.in);char[] n = null,m = null;char[] temp = {1,2,3};if(scan.hasNext())n = scan.next().toCharArray();if(scan.hasNext())m = scan.next().toCharArray();n = ReverseOrder(n);m = ReverseOrder(m);char[] ret = reverse(n,m);int length = ret.length;while(length>1 && ret[length-1] == '0')length--;for(int i=length-1; i>=0; i--)System.out.print(ret[i]);}/*** 使数组倒序排列  */private static char[] ReverseOrder(char[] a){for(int i=0; i<(a.length/2); i++){char temp = a[i];a[i] = a[a.length-1-i];a[a.length-1-i] = temp;}       return a;}/*** 按照游戏规则翻转矩阵中的硬币*/private static char[] reverse(char[] n, char[] m){char[] sqrt_n = sqrt(n);char[] sqrt_m = sqrt(m);return mult(sqrt_n,sqrt_m);}/*** 求大数的平方根(向下取整)*/private static char[] sqrt(char[] a){       int length = (a.length%2 == 1)? a.length/2+1 : a.length/2;char[] ret = new char[length];for(int i=0; i<length-1; i++)ret[i]='0';ret[length-1] = '1';for(int i=length-1; i>=0; i--){while(ret[i] <= '9'){if(compare(a,mult(ret,ret)) != 1){ret[i] = (char) (ret[i] - 1);break;}if(ret[i] < '9')ret[i] = (char) (ret[i] + 1);elsebreak;}}return ret;}/*** 求大数的乘积*/private static char[] mult(char[] a, char[] b){int[] number = new int[a.length+b.length];for(int i=0;i<number.length;i++)  number[i]=0;int a_start = 0;while(a[a_start]=='0')a_start++;int b_start = 0;while(b[b_start]=='0')b_start++;for(int i=a_start; i<a.length; i++)for(int j=b_start; j<b.length; j++){number[i+j] += (a[i]-'0') * (b[j]-'0');}for(int k=a_start+b_start; k<number.length-1; k++){number[k+1] += number[k]/10;number[k] = number[k] % 10;}char[] ret;if(number[number.length-1]==0)ret = new char[number.length-1];elseret = new char[number.length];for(int i=0; i<ret.length; i++){ret[i] = (char) (number[i] + '0');}return ret;}/** *  比较两个大数的大小* @return * -1 : 数组a的值更大;*  0 : 两个数组的值相同;*  1 : 数组a中的值更小;*/private static int compare(char[] a, char[] b){if(a.length > b.length)return 1;if(a.length < b.length)return -1;for(int i = a.length-1; i>=0; i--){if(a[i] > b[i])return 1;if(a[i] < b[i])return -1;}return 0;}
}

转载于:https://www.cnblogs.com/yuex/p/5522642.html

蓝桥杯试题:矩阵翻硬币相关推荐

  1. 蓝桥 历届试题 矩阵翻硬币 JAVA

    问题描述 小明先把硬币摆成了一个 n 行 m 列的矩阵. 随后,小明对每一个硬币分别进行一次 Q 操作. 对第x行第y列的硬币进行 Q 操作的定义:将所有第 ix 行,第 jy 列的硬币进行翻转. 其 ...

  2. 历届试题 矩阵翻硬币 蓝桥杯 大数开方 大数相乘

    历届试题 矩阵翻硬币   时间限制:1.0s   内存限制:256.0MB 问题描述 小明先把硬币摆成了一个 n 行 m 列的矩阵. 随后,小明对每一个硬币分别进行一次 Q 操作. 对第x行第y列的硬 ...

  3. 【蓝桥杯】历届试题 矩阵翻硬币

    历届试题 矩阵翻硬币 ----------------------------------------------------痞子小小崔 时间限制:1.0s 内存限制:256.0MB 问题描述 小明先 ...

  4. 历届试题 矩阵翻硬币

    历届试题 矩阵翻硬币   时间限制:1.0s   内存限制:256.0MB      问题描述 小明先把硬币摆成了一个 n 行 m 列的矩阵. 随后,小明对每一个硬币分别进行一次 Q 操作. 对第x行 ...

  5. 蓝桥杯历届试题----矩阵翻硬币

    矩阵翻硬币 问题描述 小明先把硬币摆成了一个 n 行 m 列的矩阵.随后,小明对每一个硬币分别进行一次 Q 操作.对第x行第y列的硬币进行 Q 操作的定义:将所有第 i*x 行,第 j*y 列的硬币进 ...

  6. 试题 历届试题 矩阵翻硬币

    原题链接:试题 历届试题 翻硬币 1.懒得样式,截图如下 2.思路: 首先,同时翻动两个相邻的硬币,这就意味着不同的硬币的个数一定是偶数个,如果是奇数个永远也达不到目标状态. 其次,顺序翻转就是翻转次 ...

  7. 蓝桥杯 历届试题 矩阵翻硬币(大数)

    问题描述 小明先把硬币摆成了一个 n 行 m 列的矩阵. 随后,小明对每一个硬币分别进行一次 Q 操作. 对第x行第y列的硬币进行 Q 操作的定义:将所有第 i*x 行,第 j*y 列的硬币进行翻转. ...

  8. Java实现 蓝桥杯 历届试题 矩阵翻硬币

    问题描述 小明先把硬币摆成了一个 n 行 m 列的矩阵. 随后,小明对每一个硬币分别进行一次 Q 操作. 对第x行第y列的硬币进行 Q 操作的定义:将所有第 ix 行,第 jy 列的硬币进行翻转. 其 ...

  9. 蓝桥杯--矩阵翻硬币

    历届试题 矩阵翻硬币   时间限制:1.0s   内存限制:256.0MB      问题描述 小明先把硬币摆成了一个 n 行 m 列的矩阵. 随后,小明对每一个硬币分别进行一次 Q 操作. 对第x行 ...

  10. 【蓝桥杯题解】矩阵翻硬币

    历届试题 矩阵翻硬币 时间限制:1.0s 内存限制:256.0MB 提交此题 问题描述 小明先把硬币摆成了一个 n 行 m 列的矩阵. 随后,小明对每一个硬币分别进行一次 Q 操作. 对第x行第y列的 ...

最新文章

  1. 协程Coroutines入门
  2. jQuery效果:隐藏、显示、切换、滑动、淡入淡出、动画
  3. python3 整除 取模
  4. mysql的dml全,MySQL数据管理----DML语言(全记住)(示例代码)
  5. 解决KMP看高清电影背景声大说话声小问题
  6. linux du命令重定向,df命令、du命令 、磁盘分区
  7. php 超链接新页面打开新页面,Typecho 超链接默认新窗口打开
  8. 控制台资费管理主菜单java_java毕业设计_springboot框架的高速公路收费管理系统...
  9. python 调用js_python调用JS方法
  10. 超链接显示网站 A,访问后进入网站 B
  11. c语言分析工具——函数调用关系生成图像、流程图生成器
  12. 虽然不舍但是事实 —— 纪念下 JavaEye
  13. 队列,计算机中的排队模型
  14. win10c盘扩容_Win10磁盘分区工具-无损分区助手
  15. 《守望先锋》架构设计和网络同步
  16. 60秒学脑科学常识——《科学美国人》专栏文集
  17. 如何解决 Apple ID 验证失败,无法正常使用?
  18. 转载:一字千金 句句受用
  19. 学生抖音宣传母校被吐槽“招生减章”,网友:哈哈哈哈哈哈
  20. linux 析构函数地址获取_c语言中有析构函数吗

热门文章

  1. linux cp -w,对Linux的cp命令的思考
  2. esp32树莓派_用树莓派 DIY 宠物自动喂食机,再也不用担心家里的萌宠了
  3. 业余学习python有用吗_对于那些不做编程工作的小伙伴来说,学习Python有什么用呢?...
  4. android 字体切换快捷键,Android stdio 字体设置及快捷键
  5. 学习linux中踩的坑,踩踩Linux命令中的那些坑
  6. php临时文件删除,php删除临时文件的代码示例
  7. pandas 索引去重_Pandas 同元素多列去重的实例
  8. linux防火墙规则命令意思,linux防火墙iptables配置规则分享
  9. python获取app信息的库_基于python3抓取pinpoint应用信息入库
  10. excel排名_排名数据应该用什么图表?Excel有这样的图表吗?- Excel图表教程