[题解]编程设有一个n*m方格的棋盘(1<=m,n<=100),求该棋盘包含多少正方形,长方形?
2009-06-27 03:57
681 查看
题目:
编程设有一个n*m方格的棋盘(1<=m,n<=100)求该棋盘包含多少正方形,长方形。
(1997年第三届全国青少年信息学(计算机)奥林匹克分区联赛普及组复赛试题)
网上已经有一些文章和程序来说明和解决这个问题了,我这里就是在阅读了大量的文章后的一些思考,觉得在表述上可以作为补充。
解答:
正方形和长方形都有“长”和“宽”,因此可以从这里入手,先看“长”可取的总数,再看“宽”的总数(注意正方形和长方形关于“长”和“宽”的限制条件),最后用乘方原理和加法原理得出总数就可以了。
在这里,可以注意到,无论是长方形和正方形的数量有多少,它们的和应该容易求出,这就是n*m的所有“长”的可能数*“宽”的可能数之和,即就是:当“长”和“宽”都取1时,可能数为n*m个;当“长”取1,“宽”取2时,可能数为n*(m-1)[“宽”值取2的情况共有m-1种];以此类推,……,当“长”取1,“宽”取m时,可能数为n*1。因此,可以看出当“长”取1时,总数为n * (m + m-1 + ... + 1)=n * [m*(m-1)]/2。而“长”取值的可能也分别为1~n,因此所有方形(正方形+长方形)的总数为[m*(m+1)/2]*[n*(n+1)/2]。
可以开始考试计算正方形和长方形的数量了。由于正方形对于“长”和“宽”的限制更为严格,要求相等,因此思路就产生了,首先计算出正方形的数量,然后使用上面得出的总数减去正方形的数量,剩下的就是长方形的数量了。
对于正方形数量的计算,可以采用如上同样的思路,这里就不再详细描述了,结果正方形的数量应为:(假设m>n) m*n+(m-1)*(n-1)+...+(m-n+1)*1。这样,问题就已经求解出来了。
当然,对于某些想寻根问底的朋友, 可能想知道如果直接计算长方形的数量,是怎样计算的?其实思路还是一样的,只是因为限制条件变化了,因而可能得借助列举才能更清楚。你可以按照上面的思路,把“长”和“宽”的情况都展开放到表里面,然后把总数写在横列交叉处,如下图:
![](https://oscdn.geek-share.com/Uploads/Images/Content/202003/12/b38e268e9656dc86ccf8b1e8f073d34e.jpg)
图1 在n*m表格上列出公式规律[3]
[align=left]则可以得出当a(即“长”)取值为1时,长方形的总数为:n * [ m * (m-1) ] / 2
[/align]当a取值为2时,长方形的总数为:(n-1) * [ m * (m-1) / 2 + 1 ]
以此类推,当a取值为n时,长方形的总数为:1 * [ m * (m-1) / 2 + (n-1) ]
这样就可以理解a从1变化到n时,长方形每次累加的值为:(n-a+1)*[m*(m-1)/2+b-1]
这里尤其要注意一点,变量b存在的必要性。可用如下一张图来描述:
![](https://oscdn.geek-share.com/Uploads/Images/Content/202003/12/42450580f17b95ecd8d8d7e6afffbc77.jpg)
图2 当n=30 / m=20时,长方形的总数情况(By Microsoft Excel)
可以看到,当m小于n时,变量b的值应当不发生变化,而变量a的值还要一直变化到n,反之亦如此。这样,我们就可以编写程序如下:
1 #include <stdio.h>
2
3 int main()
4 {
5 int n, m, s, t;
6 s=0, t=0;
7 scanf("%d %d", &n, &m);
8 int a = 1;
9 int b = 1;
int c = (m*(m-1)) >> 1;
while(a <= n)
{
if(a == b)
{
s = s + (n-a+1) * (m-b+1);
}
t = t + (n-a+1)*(c+b-1);
if(a <= n)
{
a ++;
}
if(b <= m)
{
b ++;
}
}
printf("%d %d", s, t);
return 0;
}
需要注意的是其中循环变量a与b的变化。在循环中,也对正方形的数量进行了求解。
此程序我认为其优点是相对简单,数学运算公式比较清楚,参考[2]中的算法我始终还是有点不明白,因此就我想到的这个写下来了,仅供参考,欢迎讨论!
最后,感谢网友提供的如下资料,能够使我解决了这个问题,从而对此类问题有了更清醒的认识,谢谢!
[1] 百度百科:http://zhidao.baidu.com/question/85045813.html?fr=qrl
[2] QQ空间:http://qzone.qq.com/blog/82314038-1211596276
[3] 程序员联员开发网:第一次实验报告 http://www.pudn.com/downloads37/sourcecode/windows/other/detail123530.html
编程设有一个n*m方格的棋盘(1<=m,n<=100)求该棋盘包含多少正方形,长方形。
(1997年第三届全国青少年信息学(计算机)奥林匹克分区联赛普及组复赛试题)
网上已经有一些文章和程序来说明和解决这个问题了,我这里就是在阅读了大量的文章后的一些思考,觉得在表述上可以作为补充。
解答:
正方形和长方形都有“长”和“宽”,因此可以从这里入手,先看“长”可取的总数,再看“宽”的总数(注意正方形和长方形关于“长”和“宽”的限制条件),最后用乘方原理和加法原理得出总数就可以了。
在这里,可以注意到,无论是长方形和正方形的数量有多少,它们的和应该容易求出,这就是n*m的所有“长”的可能数*“宽”的可能数之和,即就是:当“长”和“宽”都取1时,可能数为n*m个;当“长”取1,“宽”取2时,可能数为n*(m-1)[“宽”值取2的情况共有m-1种];以此类推,……,当“长”取1,“宽”取m时,可能数为n*1。因此,可以看出当“长”取1时,总数为n * (m + m-1 + ... + 1)=n * [m*(m-1)]/2。而“长”取值的可能也分别为1~n,因此所有方形(正方形+长方形)的总数为[m*(m+1)/2]*[n*(n+1)/2]。
可以开始考试计算正方形和长方形的数量了。由于正方形对于“长”和“宽”的限制更为严格,要求相等,因此思路就产生了,首先计算出正方形的数量,然后使用上面得出的总数减去正方形的数量,剩下的就是长方形的数量了。
对于正方形数量的计算,可以采用如上同样的思路,这里就不再详细描述了,结果正方形的数量应为:(假设m>n) m*n+(m-1)*(n-1)+...+(m-n+1)*1。这样,问题就已经求解出来了。
当然,对于某些想寻根问底的朋友, 可能想知道如果直接计算长方形的数量,是怎样计算的?其实思路还是一样的,只是因为限制条件变化了,因而可能得借助列举才能更清楚。你可以按照上面的思路,把“长”和“宽”的情况都展开放到表里面,然后把总数写在横列交叉处,如下图:
![](https://oscdn.geek-share.com/Uploads/Images/Content/202003/12/b38e268e9656dc86ccf8b1e8f073d34e.jpg)
图1 在n*m表格上列出公式规律[3]
[align=left]则可以得出当a(即“长”)取值为1时,长方形的总数为:n * [ m * (m-1) ] / 2
[/align]当a取值为2时,长方形的总数为:(n-1) * [ m * (m-1) / 2 + 1 ]
以此类推,当a取值为n时,长方形的总数为:1 * [ m * (m-1) / 2 + (n-1) ]
这样就可以理解a从1变化到n时,长方形每次累加的值为:(n-a+1)*[m*(m-1)/2+b-1]
这里尤其要注意一点,变量b存在的必要性。可用如下一张图来描述:
![](https://oscdn.geek-share.com/Uploads/Images/Content/202003/12/42450580f17b95ecd8d8d7e6afffbc77.jpg)
图2 当n=30 / m=20时,长方形的总数情况(By Microsoft Excel)
可以看到,当m小于n时,变量b的值应当不发生变化,而变量a的值还要一直变化到n,反之亦如此。这样,我们就可以编写程序如下:
1 #include <stdio.h>
2
3 int main()
4 {
5 int n, m, s, t;
6 s=0, t=0;
7 scanf("%d %d", &n, &m);
8 int a = 1;
9 int b = 1;
int c = (m*(m-1)) >> 1;
while(a <= n)
{
if(a == b)
{
s = s + (n-a+1) * (m-b+1);
}
t = t + (n-a+1)*(c+b-1);
if(a <= n)
{
a ++;
}
if(b <= m)
{
b ++;
}
}
printf("%d %d", s, t);
return 0;
}
需要注意的是其中循环变量a与b的变化。在循环中,也对正方形的数量进行了求解。
此程序我认为其优点是相对简单,数学运算公式比较清楚,参考[2]中的算法我始终还是有点不明白,因此就我想到的这个写下来了,仅供参考,欢迎讨论!
最后,感谢网友提供的如下资料,能够使我解决了这个问题,从而对此类问题有了更清醒的认识,谢谢!
[1] 百度百科:http://zhidao.baidu.com/question/85045813.html?fr=qrl
[2] QQ空间:http://qzone.qq.com/blog/82314038-1211596276
[3] 程序员联员开发网:第一次实验报告 http://www.pudn.com/downloads37/sourcecode/windows/other/detail123530.html
相关文章推荐
- Problem Description 有一个长度为n(n<=100)的数列,该数列定义为从2开始的递增有序偶数,现在要求你按照顺序每m个数求出一个平均值,如果最后不足m个,则以实际数量求平均值。编程输出该平均值序列。 Input 输入数据有多组,每组占一行,包含两个正整数n和m,n和m的含义
- GCD XOR UVA 12716 找规律 给定一个n,找多少对(a,b)满足1<=b<=a<=n,gcd(a,b)=a^b;
- Problem Description 青年歌手大奖赛中,评委会给参赛选手打分。选手得分规则为去掉一个最高分和一个最低分,然后计算平均得分,请编程输出某选手的得分。 Input 输入数据有多组,每组占一行,每行的第一个数是n(2<n<=100),表示评委的人数,然后是n个评委的打分。 O
- 在平面N*N(N<=500)的格子上有一些障碍物。要求找到一个最大的正方形,它的内部不包含障碍物
- 有一头母牛,它每年年初生一头小母牛。每头小母牛从第四个年头开始,每年年初也生一头小母牛。请编程实现在第n年的时候,共有多少头母牛?输入数据由多个测试实例组成,每个测试实例占一行,包括一个整数n(0<n
- Problem Description 有n(n<=100)个整数,已经按照从小到大顺序排列好,现在另外给一个整数x,请将该数插入到序列中,并使新的序列仍然有序。 Input 输入数据包含多个测试实例,每组数据由两行组成,第一行是n和m,第二行是已经有序的n个数的数列。n和m同时为0标示输入数
- C - Aladdin and the Flying Carpet 有多少种长方形满足面积为a(<=10^12),且最短边>=b;长方形边长为整数,且一定不可以是正方形。
- 有一个长度为n(n<=100)的数列,该数列定义为从2开始的递增有序偶数(2,4,6,8,10,…),现在要求你按照顺序每m个数求出一个平均值,如果最后不足m个,则以实际数量求平均值。编程输出该平均值
- 动态生成数组保存:已知一个数组20个元素(随机 1~100之间包含1和100),求大于平均数的元素个数,并动态生成一个新数组保存
- scala 打印一个乘法口诀表 (<<scala 编程>> P87)
- 题目:一个整数,它加上100后是一个完全平方数,再加上168又是一个完全平方数,请问该数是多少?
- Educational Codeforces Round 8 E. Zbazi in Zeydabad(给你一个n*m矩阵,每个点可能是'.'或者'z',问有多少种Z子型(Z为一个正方形))
- 一串首尾相连的珠子(m 个),有N 种颜色(N<=10),设计一个算法,取出其中一段,要求包含所有N 中颜色,并使长度最短。并分析时间复杂度与空间复杂度。
- 在一个字符串(1<=字符串长度<=10000,全部由大写字母组成)中找到第一个只出现一次的字符,并返回它的位置
- 一个射击运动员打靶,靶一共有10环,连开10枪打中90环的可能性有多少种?请用递归算法编程实现。
- n*m棋盘的长方形个数和正方形个数
- 一个整数,加上100后是一个完全平方数,再加上168后也是一个完全平数,求该数是多少。
- 一个M * N的方格,从左下角走到右上角有多少种走法?
- 输入n(n<100)个数,找出其中最小的数,将它与最前面的数交换后输出这些数.输入数据有多组,每组占一行,每行的开始是一个整数n,表示这个测试实例的数值的个数,跟着就是n个整数。n=0表示输入的结束,
- 编程中的一个易错点:判断某个点是否超出棋盘边界