P2241 统计方形(数据加强版)

原题
这题洛谷上归到暴力枚举了,但是我认为不用暴力枚举,用数学方法就可以解决。

首先,我们知道,在任意一个长方形中,求小长方形(包括小正方形)的数量的公式是:
s = ∑ i = 1 n i × ∑ j = 1 m j s=\sum_{i=1}^n i×\sum_{j=1}^m j s=i=1ni×j=1mj
但是,这题让我们求的并不是包括小正方形的小长方形数,但是可以先把包括小正方形的小长方形数求出来,这个方法是我自己推出来的😄,我们可以举例说明:

这是一个正方形,它里面的小正方形的个数怎么求呢?

这我相信难不倒大家,边长为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+(a1)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;
}
posted @ 2021-02-08 15:48  easyf12  阅读(92)  评论(0)    收藏  举报