P2241 统计方形(数据加强版)
原题
这题洛谷上归到暴力枚举了,但是我认为不用暴力枚举,用数学方法就可以解决。
首先,我们知道,在任意一个长方形中,求小长方形(包括小正方形)的数量的公式是:
s
=
∑
i
=
1
n
i
×
∑
j
=
1
m
j
s=\sum_{i=1}^n i×\sum_{j=1}^m j
s=i=1∑ni×j=1∑mj
但是,这题让我们求的并不是包括小正方形的小长方形数,但是可以先把包括小正方形的小长方形数求出来,这个方法是我自己推出来的😄,我们可以举例说明:

这是一个正方形,它里面的小正方形的个数怎么求呢?
这我相信难不倒大家,边长为1的有16个,边长为2的有9个,边长为3的有4个,边长为4的有1个。就是:
16
+
9
+
4
+
1
=
30
(
个
)
16+9+4+1=30(个)
16+9+4+1=30(个)
那,大家看着四个数,心中可能有一些联想:16=4×4,9=3×3,4=2×2,1=1×1。这样就把它们拆开了。这样我们就可以总结出求正方形中小正方形个数的公式了:
n
=
a
2
+
(
a
−
1
)
2
+
.
.
.
+
1
2
n=a^2+(a-1)^2+...+1^2
n=a2+(a−1)2+...+12
那么,这样的长方形中有多少个小正方形呢?

看到这个长方形,大家可能就没招了。但是,把这个长方形照葫芦画瓢,两个边长换成长和宽,可不可以呢?
5
×
4
+
4
×
3
+
3
×
2
+
2
×
1
=
40
5×4+4×3+3×2+2×1=40
5×4+4×3+3×2+2×1=40
按照原来的方法数一数,我们可以发现,这样是可以的。但是,要注意,这里要先将两个数做比较,5>4,所以就看4什么时候减到1,只要4减到1,就可以不加了。
到这里,数学推导就结束了,下面奉上代码:
#include <bits/stdc++.h>
using namespace std;
int main() {
long long n,m,s1=0,s2=0,s=0,t=0;
cin>>n>>m;
for(int i=1;i<=n;i++){
s1=s1+i;
}
for(int i=1;i<=m;i++){
s2=s2+i;
}
s=s1*s2;
if(n>=m){
for(int i=m;i>=1;i--) {
t = t + i * n;
n--;
}
}
if(n<m){
for(int i=n;i>=1;i--) {
t = t + i * m;
m--;
}
}
cout<<t<<" "<<s-t;
return 0;
}

浙公网安备 33010602011771号