前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Python|蓝桥杯—矩阵翻硬币

Python|蓝桥杯—矩阵翻硬币

作者头像
算法与编程之美
发布2020-03-25 17:38:26
6360
发布2020-03-25 17:38:26
举报
文章被收录于专栏:算法与编程之美

问题描述

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

资源约定:

峰值内存消耗(含虚拟机) < 256M

CPU消耗 < 2000ms

解决方案

本题的思路在于找到翻动之后变成正面的硬币,有两个方向可以思考:一是对所有的硬币再次Q操作,但是题目中要求使用更加简单的方法;二是找到硬币翻动的规律,按照题目的要求,已经在暗示需要找到这个规律。

众所周知,当硬币翻动次数为奇数时,硬币面才会变化,而偶数时不变。仔细理解题目:对(x,y)点上的硬币进行Q操作的意思是对所有在矩阵中的(1*x,1*y)、(1*x,2*y)、(1*x,3*y)……满足条件的点上的硬币同时进行翻动,那么同样的对于(x,y)这一点来说,被翻动的次数就等于x的真因子和y的真因子的组合累计。例如:(2,4)这个点被翻动的次数是(1,1),(1,2),(1,4),(2,1),(2,2),(2,4),这些点在进行q操作的累计。

通过上述分析,可以得到(x,y)这一点被翻动的次数N=x的真因子个数和y的真因子个数的乘积。而且只有当奇数与奇数相乘才会得到奇数,对于自然数,只有平方数的真因子个数为奇数(质数和偶数的因子成对出现)。所以,只有当(x,y)中x和y同时为平方数的时候,这一点上的硬币被翻动后才会改变。

所以问题变成了在n*m的矩阵中找到行和列都为平方数的组合总数,且n中包含的平方数=向下取整,那么问题就类似于求*。同时还不要忘记题目中的数据规模,最后一部分数据是非常大的,使用python中开方函数无法做到,所以还需要对于这些数进行逐位的试探,找到它的平方根,详见代码。

Pytho代码:

n,m=input().split(' ')def fanyingbi(n,m): if len(n) % 2 == 0: n_len = len(n) / 2 else: n_len = (len(n) // 2) + 1 n_len = int(n_len) n_1 = [] n_2 = [] for i in range(n_len):#构建全为0的列表模拟平方根 n_1.append('0') for i in range(n_len): n_2.append('0') for x in range(n_len): for y in range(1, 10): n_1[x] = str(y)#将(1-9)插入x位置 n_2[x] = str(y - 1)#由于减了1,也不会漏掉0的情况 a = ''.join(n_1)#字符串化 b = ''.join(n_2) if eval(a) ** 2 > eval(n) and eval(b) ** 2 <= eval(n):#当x位上的数字满足条件时,跳出循环 break n_sum = eval(''.join(n_2)) if len(m) % 2 == 0: m_len = len(m) / 2 else: m_len = (len(m) // 2) + 1 m_len = int(m_len) m_1 = [] m_2 = [] for i in range(n_len):#构建全为0的列表模拟平方根 m_1.append('0') for i in range(n_len): m_2.append('0') for x in range(m_len): for y in range(1, 10): m_1[x] = str(y)#将(1-9)插入x位置 m_2[x] = str(y - 1)#同时不要忘记0的情况 a = ''.join(m_1)#字符串化 b = ''.join(m_2) if eval(a) ** 2 > eval(n) and eval(b) ** 2 <= eval(n):#当平方根满足条件时,跳出循环 break m_sum=eval(''.join(m_2)) return n_sum*m_sum

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-03-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 算法与编程之美 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档