2020牛客寒假算法基础集训营1 A
程序员文章站
2022-06-07 13:05:47
...
题目
思路
找底、高一个为1一个为2的三角形
已知共有n行m列
第一类:
在每一行上,以=长为2的边为底(黑色边)向外找三角形
-
每3个点构成一个长为2的底,那么一行有m个点(m列),就有(m-2)个底。
相邻行的点均可做这个底对应的那个顶点,那么一个底就有m个三角形(相邻行有m个点)
那么这一行就有(m-2) * m 个三角形,两行就有 (m-2) * m * 2个
-
以两行为一个大单位,那么在nm的格点中就有(n-1)个这样的大单位。
那么nm的格点中就有 (m-2) * m * 2 * (n-1) 个三角形
第二类:
与第一类类似,
但是,是在每一列上,以=长为2的边为底(黑色边)向外找三角形
分析与第一类类似,只是行列的关系对调。
公式是 (n-2) * n * 2 * (m-1)
第三类:
是在每一行上,找以=长为1的边为底(黑色边),并且高与坐标轴不垂直的三角形
如果高与坐标轴垂直,就与前两种情况找的重复了!!!如下:
下图为不垂直的:
- 每2个点构成一个长为1的底,那么一行有m个点(m列),就有(m-1)个底。
隔行的点刨除去2个形成垂直的高的点,剩下(m-2)个可以当顶点的点,那么一个底就有(m-2)个三角形
那么这一行就有(m-1) * (m-2) 个三角形,三行就有 (m-1) * (m-2) * 2个(中间那一行不能形成这样的三角形)
- 以三行为一个大单位,那么在nm的格点中就有(n-2)个这样的大单位。
那么nm的格点中就有 (m-1) * (m-2) * 2 * (n-2) 个三角形
即(m-1) * (m-2) * (2n-4)
第四类:
与第三类类似,但是
是在每一列上,找以=长为1的边为底(黑色边),并且高与坐标轴不垂直的三角形
分析与第三类类似,只是行列的关系对调。
公式为(n-1) * (n-2) * (2m-4)
特殊情况:
if(n==2&&m==2){cout<<'0'<<endl;return 0;}//2点*2点
AC代码
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
typedef long long ll;
inline ll mm(ll a, ll b, ll m)
{
ll c = a*b-(ll)((long double)a*b/m+0.5)*m;
return c<0 ? c+m : c; //就是算的a*b%m;
}
int main()
{
int n,m;
cin>>n>>m;
if(n==2&&m==2){cout<<'0'<<endl;return 0;}
else
{
cout<<(mm(mm(m-2,m*2,1000000007),n-1,1000000007)+mm(mm(n-2,n*2,1000000007),m-1,1000000007)+mm(mm(m-1,m-2,1000000007),n*2-4,1000000007)+mm(mm(n-1,n-2,1000000007),m*2-4,1000000007))%1000000007<<endl;
}
return 0;
}