c语言洛谷刷题日记:P2241 统计方形(数据加强版)

看题目点这里


这道题最大的问题其实就是超时,下面直接上一段愚蠢的代码:

#include<stdio.h>
int main()
{
	int n, m;
	scanf("%d%d", &n, &m);
	int count1 = 0;
	int count2 = 0;
	int num = n < m ? n : m;
	for (int i = 0; i < n; i++)
		for (int j = 0; j < m; j++)
			for (int k = 0; k < n; k++)
				for (int l = 0; l < m; l++)
				{
					if (i + k < n && l + j < m)
					{
						if (k == l)
							count1++;
						else
							count2++;
					}
				}
	printf("%d ", count1);
	printf("%d", count2);
}//暴力枚举,时间超过了

套了四层循环,搁谁不迷糊


所以我们就得找找规律,简化简化代码。

首先我们得懂一个数学概念:正方形跟长方形都是矩形,本题中的长方形不包括正方形,所以长方形就等于矩形减去正方形。

下面我们就找找正方形的规律:

当正方形边长为1 的时候,不难看出其个数有     (n-0)*(m -0)    个,

为2时,有(n-1)*(m -1)个,

为3时,有(n-2)*(m -2)个,

以此类推,为min(n,m)时有(n-min(n,m))*(m -min(n,m))个,也就是一个。

所以我们能通过一层循环就把它求出来:


int num1=n>m?m:n;//n和m中的较小值
for (long long i = 0; i < num1; i++)
	{
		count1 += (n - i) * (m - i);
	}

那么矩形该怎么求呢?

我们可以根据求正方形的思想来求矩形的个数:

当长为1,宽为1 的个数有(n-0)*(m-0)个

当长为1,宽为2 的个数有(n-0)*(m-1)个

........

........

当长为1,宽为m的个数有(n-0)*(m-m)个

当长为2,宽为1 的个数有(n-1)*(m-0)个

当长为2,宽为2 的个数有(n-1)*(m-2)个

.........

.........

最后我们就能通过两层循环来求出矩形的个数:


	for (long long i = 0; i < num1; i++)//数学问题
	{
		for (long long j = 0; j < num2; j++)
		{
			count2 += (long long)(num1 - i) * (num2 - j);
		}
	}

最后两段代码嵌套一下就得到了全AC的代码:


#include<stdio.h>
int main()
{
	long long n, m;
	scanf("%lld%lld", &n, &m);
	long long count1 = 0;
	long long count2 = 0;
	long long num1 = n < m ? n : m;
	long long num2 = n > m ? n : m;
	for (long long i = 0; i < num1; i++)//数学问题
	{
		for (long long j = 0; j < num2; j++)
		{
			count2 += (long long)(num1 - i) * (num2 - j);
		}
		count1 += (n - i) * (m - i);
	}
	printf("%lld ", count1);
	printf("%lld", count2 - count1);
}

都写long long是因为题目的数据有点大。


最后,如果这篇文章对你有所启发或者没什么启发那么就点点赞,收收藏,转转发,你们的支持就是我前进的动力(一个赞一道题),下次再见。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值