P1548 棋盘问题

题目

洛谷 P1548

解法一

思路

n,m范围只有100,所以枚举左上角,枚举右下角,判断是正方形还是长方形

时间复杂度

枚举1个是O(n2),所以复杂度为O(n4)

代码

#include<stdio.h>

int main()
{
	int n,m,a=0,b=0,i,j,k,l;
	scanf("%d%d",&n,&m);
	for(i=1;i<=n;++i)
		for(j=1;j<=m;++j)
			for(k=i;k<=n;++k)
				for(l=j;l<=m;++l)
					if(k-i==l-j) a++;
					else b++;
	printf("%d %d",a,b);
}  

解法二

思路

从边长方向考虑:n行m列的大矩形内能找出多少i行j列的小矩形?
小矩形一共有i行,它的第1行可以在大矩形的第1—n-i+1行,它的最后1行可以在大矩形的第i—n行
小矩形一共有j列,它的第1列可以在大矩形的第1—m-j+1列,它的最后1列可以在大矩形的第j—m列
所以枚举边长i 和 j,可以有(n-i+1)(m-j+1)个

时间复杂度

两重循环枚举边长,O(n2)

代码

#include<stdio.h>

int main()
{
	int n,m,a=0,b=0,i,j;
	scanf("%d%d",&n,&m);
	for(i=1;i<=n;++i)
		for(j=1;j<=m;++j)
			if(i==j) a+=(n-i+1)*(m-j+1);
			else  b+=(n-i+1)*(m-j+1);
	printf("%d %d",a,b);
}

解法三

思路

前面解法看起来很有规律,所以我们是否能推出一个公式?
先考虑能找出多少个矩形(长方形+正方形)

  • 思考方向一:把上面思路二的两重for循环展开,即把(n-i+1)(m-j+1)里的i和j扩展开,就是(1+2+3+……+n)(1+2+3+……+m),用等差数列求和公式得到n(n+1)m(m+1)/4
  • 思考方向二:相当于从n+1个横线和m+1个竖线中,任选2条横线,任选2条竖线,有多少种选法。因为每一种选法都可以构成一个矩形。用组合数得到 C(n+1,2)*C(m+1,2)=n(n+1)m(m+1)/4

再推出正方形的个数公式,减去就是长方形的个数
正方形的个数公式推导:
推导过程

时间复杂度

套公式直接出解,O(1)

代码

#include<stdio.h>

int main()
{
	int n,m,a,b,t;
	scanf("%d%d",&n,&m);
	t=n<m ? n : m;
	a=(n*m+n+m+1)*t-t*(t+1)/2*(n+m+2)+t*(t+1)*(2*t+1)/6; 
	b=n*m*(n+1)*(m+1)/4;
	printf("%d %d",a,b-a);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值