算法题——立方体的体对角线穿过多少个正方体万仓一黍

这道题是笔者当年参加竞赛的题目,多年来一直未得其解,久久不能释怀。近日,重新拿起该题细细研究,终于将其解出,著文以记之。

问题描述:

长方体长X,宽Y,高Z。X、Y、Z都是正整数。长方体由长1、宽1、高1的正方体堆积而成。那么长方体的体对角线穿过多少个正方体?

这个题考量三维空间的想象。近日研究的时候,尝试先考量二维的情况,在求解出二维的情况下,在推广到三维里。下面是二维情况下的问题描述

长方形长X,宽Y。X、Y都是正整数。长方形由长1、宽1的正方形组成。那么长方形的对角线穿过多少个正方形?

以实例说明。长方形长6,宽4。长方形由长1、宽1的正方形组成。那么长方形的对角线穿过多少个正方形?

这个还是比较简单的,直接用图表示即可,如下图所示:

如上图所示,对角线一共穿过8个正方形(灰色部分)。但是,我们不可能每个问题都画图表示,比如长777,宽581的长方形的解就很难画图表示(数字太大,不容易精确表示)。

仔细看看,这8个正方形实际上把对角线分成了8段。线段的端点是对角线和水平线(或竖直线)的交点。

于是,问题似乎可以转化成

要求穿过多少个正方形,实际上相当于求有多少个线段

要求有多少个线段,实际上相当于求对角线和水平线和垂直线的交点的个数

把上图放在平面直角坐标系中,左下角坐标为(0,0),右上角坐标为(6,4)

则对角线的直线方程为

和我们一般想象中的直线方程不太一样。没关系,首先这个是正确的直线方程,其次是为了和后面的三维中的直线方程的表现形式统一。

我们把对角线和水平线(或竖直线)的交点在图上标示出来(为了后文的描述方便,我用不同颜色标示点)

左下角的起点用灰色标示,红色的点标示对角线和竖直线的交点(交点的横坐标是整数),绿色的点标示对角线和水平线的交点(交点的纵坐标是整数)

起点不算,则穿过的方块数和线段数和点的个数一致(都是8个)。

红色点的坐标(横坐标是整数)分别是:

个数和长方形的长的数值是一致的(是6)

绿色点的坐标(纵坐标是整数)分别是:

个数和长方形的宽的数值是一致的(是4)

可以看出,红色点和绿色点有2个点是重合的(图上用半红半绿的点标示),因此这些点合在一起就是如下(按照和起点的远近来进行排序)

于是该问题的求解过程可以如下表示:

1、求出横坐标是整数的点的个数,就是长方形长的数值。本题是6

2、求出纵坐标是整数的点的个数,就是长方体宽的数值。本题是4

3、求出步骤1和步骤2中重合的点的个数,也就是横纵坐标都是整数的点的个数。本题是2

4、问题的答案:步骤1的答案+步骤2的答案-步骤3的答案。本题是6+4-2=8

步骤1、2、3、4中,关键是步骤3,如何求出步骤1和步骤2中重合的点的个数,也就是横纵坐标都是整数的点的个数。

最大公约数:正整数a和b,若a能被b整除,则a是b的倍数,b是a的约数。正整数a和b中约数最大的那个称为a和b的最大公约数,记作gcd(a,b)

本题中,(4,6)=2,正好是步骤3的答数,是巧合么?不是,接下来我们来证明。

证明:长X、宽Y的长方形,对角线经过双整数点(横纵坐标都是整数)的个数为gcd(X,Y)(注:不算起点)

证:令x1=X/gcd(X,Y),y1=Y/gcd(X,Y)。则x1和y1都是整数,且x1和y1互质(除1以外,没有公约数)。

对角线所在的直线方程为

当x取整数时(1≤x≤X)时,要使y也是整数,则x必须取x1的倍数(这样才能把分母完全约掉)

而在1到X之间,x1的倍数一共有gcd(X,Y)个

证明完毕

综上所述:长方形长X,宽Y。X、Y都是正整数。长方形由长1、宽1的正方形组成。那么长方形的对角线穿过多少个正方形?

其解为:Ans=X+Y-gcd(X,Y),可以用下图表示

例如:

长6,宽4的长方形的对角线穿过6+4-gcd(6,4)=6+4-2=8个正方形

长5,宽3的长方形的对角线穿过5+3-gcd(5,3)=5+3-1=7个正方形

长12,宽8的长方形的对角线穿过12+8-gcd(12,8)=12+8-4=16个正方形

扩展到三维。长方体长X,宽Y,高Z。X、Y、Z都是正整数。长方体由长1、宽1、高1的正方体堆积而成。那么长方体的体对角线穿过多少个正方体?

长X、宽Y、高Z的立方体的体对角线的直线方程是

这个方程虽然有点怪,但是学过空间解析几何的都明白这个方程的正确性

求解的过程和二维的类似,也是找寻坐标是整数的点。可以用下图表示:

其解为:Ans=X+Y+Z-gcd(X,Y)-gcd(X,Z)-gcd(Y,Z)+gcd(X,Y,Z)

例如:

长5,宽3,高4的长方体的体对角线穿过5+3+4-gcd(5,3)-gcd(5,4)-gcd(3,4)+gcd(5,3,4)=5+3+4-1-1-1+1=10个正方体

长8,宽6,高3的长方体的体对角线穿过8+6+3-gcd(8,6)-gcd(8,3)-gcd(6,3)+gcd(8,6,3)=8+6+3-2-1-3+1=12个正方体

长12,宽8,高6的长方体的体对角线穿过12+8+6-gcd(12,8)-gcd(12,6)-gcd(8,6)+gcd(12,8,6)=12+8+6-4-6-2+2=16个正方体

下图是长5,宽3,高4的长方体的体对角线穿过正方体的示意图,一共10个正方体,你看清了么?

这个题历时若干年,总是百思不得其解。也是今朝灵光一闪,终于把该题解决了。也总算是一块石头落了地

THE END
0.动手学PyTorch知识点汇总1 创建一个5×35\times35×3的随机初始化的tensor: x=torch.rand(5,3) AI运行代码python 1 创建一个5×35\times35×3的long型全0的tensor: x=torch.zeros(5,3,dtype=torch.long) AI运行代码python 1 创建一个对角线都是1,其他全是0的4×44\times44×4矩阵(即单位矩阵): jvzquC41dnuh0lxfp0tfv8pmkpm`gmh1ctzjeuj1fgzbkux134629:977
1.生成对角线元素为1的矩阵这篇博客主要探讨Python中的numpy库,特别是numpy.eye()函数的使用。该函数用于生成一个对角线元素为1的矩阵。在第一个代码示例中,它创建了一个3x3的矩阵,对角线上的元素均为1。当改变参数k时,如k=1,对角线会偏移。博客鼓励读者通过实践理解此函数并参与讨论。 jvzquC41dnuh0lxfp0tfv8qkwlooi€jk:8711jwvkerf1mjvckrt1:76:;<57:
2.DataScienceNumpy基础(一)ones_like# 根据给定的数组生成形状一样的全1的数组 zeros# 根据给定的形状和类型生成全0的数组 zeros_like# 根据给定的数组生成形状一样的全1的数组 eye# 生成一个N*N的特征矩阵(对角线为1,其余为0) linspance# 返回在间隔[开始,停止]上计算的num个均匀间隔的样本 jvzquC41dnuh0ryrwd4og}4537;79A:1xkkxuyfeg/833?;221
3.如何生成对角矩阵numpy.diagpython给定对角线上元素,我想生成对角矩阵,在网上搜了一下,竟然都是numpy.diagonal。 这个函数的作用是提取给定矩阵的对角元素,当然不是我想要的。 后来发现numpy.diag才是生成对角矩阵的函数,所以写此文章记录之。 1 2 3 4 5 6 7 importnumpy as np a=[1,2,3] jvzquC41yy}/lk:30pku1jwvkerf1;997;>/j}r
4.2多元数据图形|多元统计分析讲义触须线长度不超过盒子长度的1.5倍,触须线外的点称为离群值,离群值较多的数据需要特殊方法,离群值应仔细检查。 2.2.3.2数据框中多个变量的盒形图 如果boxplot()的自变量是一个各列都是数值型的数据框,则会对数据框每一列作盒形图并且画到同一坐标系中,有利于比较各个变量的分布。如,各省城镇居民收入、支出的jvzquC41yy}/ojyj0rqv0niw0et0vnfejgxt1unfh1ipw{xg1o|s1v{tpqzfu8mvon5`owpqvkt1v{t/ixbrq3jvor
5.使用numpy包生成主对角线上全为1的矩阵python对角线元素为1的矩阵在科学计算中,我们经常需要生成单位矩阵,即主对角线上元素全为1的矩阵。那么如何能够生成主对角线上全为1的矩阵呢?这里我们介绍三种方法。 方法一: np.eye():返回一个对角线上是1,其他位置上全是0的二维矩阵。 代码如下: importnumpyasnpclassDebug:defmainProgram(self):x1=np.eye(2)print(x1)if__name__jvzquC41dnuh0lxfp0tfv8z233<:;?781cxuklqg1fkucrqu13698A96;2
6.多重循环打印图形(4)——打印斜对角线为1,其他为0的矩阵(0000100010本文介绍了一个使用C语言实现的简单程序,该程序能够根据用户输入的行数和列数打印出特定形式的矩阵。矩阵的打印遵循一定的规律,每行以'1'为中心,两侧填充'0'。 #define_CRT_SECURE_NO_WARNINGS//为解决scanf函数不安全的警告问题 #include<stdio.h> jvzquC41dnuh0lxfp0tfv8vsa6877B98:1gsvrhng1jfvjnnu1>64>;9:5
7.建立并输出一个10*10的矩阵,该矩阵对角线元素为1,其余元素均为0这篇博客介绍了如何使用C语言编写程序,生成一个10x10的矩阵,其中对角线上的元素为1,其余元素为0。提供了多个不同的代码示例来实现这一功能。 编写程序,建立并输出一个10*10的矩阵,该矩阵对角线元素为1,其余元素均为0. 关注:243 答案:5 mip版 解决时间 2021-01-29 05:20 jvzquC41dnuh0lxfp0tfv8|gkzooa;>8;:6758ftvkimg8igvcomu86394:92=8
8.第1次作业Numpy练习爱笑呀#创建一个对角线为1,2,3,4的数组importnumpy as np b=np.diag([1,2,3,4])#使用diag创建对角线为(1,2,3,4),其他元素为0的矩阵print(b) 3.数组归一化操作 生成一个随机的5*5矩阵,找出最大值和最小值,然后把最大值和最小值分别用1和0表示,其他值则介于在0和1中间。 jvzquC41yy}/ewgnqiy/exr1NUnvc8u133;7:A8;0jznn
9.R语言中矩阵常用的操作(笔记)r语言对角矩阵1.1矩阵的生成 生成一个4行4列的矩阵,这里用1~16数字。 mat <- matrix(1:16,4,4) mat 一键获取完整项目代码R 1 2 3 1.2 提取主对角线 diag(mat) 一键获取完整项目代码R 1 1 6 11 16 1.3 生成对角线为1的对角矩阵 m1 <- diag(4) m1 jvzquC41dnuh0lxfp0tfv8~klkgpdjsk1cxuklqg1fkucrqu19>9:9526
10.魔方阵生成算法解析本文详细介绍了一种生成魔方阵的算法,包括其核心步骤和实现代码。魔方阵是一种特殊的方阵,其每行、每列及对角线上的元素之和相等。文章通过实例展示了三阶魔方阵的生成过程,并提供了完整的C++代码实现。 魔方阵: 它是一个方阵 它的每一行、每一列、对角线之和均相等 jvzquC41dnuh0lxfp0tfv8Xjgtxzabzg1cxuklqg1fkucrqu1:983==:7
11.动手学深度学习笔记一腾讯云开发者社区创建一个满足正态分布(0,1)的张量 torch.rand(m,n) 随机生成在(0,1)一个m行n列的张量 torch.ones(m,n) 创建一个全1的m行n列的张量 torch.zeros(m,n,dtype=张量类型) 创建一个符合张量类型的全0m行n列的张量 torch.eye(m,n) 生成一个m行n列的对角线为1,其他为0的张量 函数(生成行向量的) jvzquC41enuvf7ygpekov7hqo1jfxnqqrgx0c{ykenk03?=49:8
12.python输出n阶矩阵主对角线元素为1print [matrix[l-1-i][i] for i in range(l-1,-1,-1)] # [ 2, 5, 2, -1] 但是我很难想出一种生成所有对角线的方法。 我正在寻找的输出是: [[-2], [9, 5], [3,-6, 3], [-1, 2, 5, 2], [8, 7, 1], [-4, 3], [8], jvzquC41dnuh0lxfp0tfv8|gkzooa<>78:8458ftvkimg8igvcomu86339=749<
13.构建一个4*4的数组,要求数组对角线为1,其他值为5python这篇博客通过一个Python代码示例展示了如何使用numpy库生成并操作随机数组。首先,创建了一个4x4的二维数组,其元素为1到100的随机整数。接着,遍历数组并按行打印所有元素,同时找出每行的最小值和每列的最大值。此外,根据用户输入,程序能输出特定行的元素以及指定列范围内的新数组。这涵盖了numpy的基本操作,包括数组jvzquC41dnuh0lxfp0tfv8m{uuyt1jwvkerf1mjvckrt1:7643>:3;