2020牛客寒假算法基础集训营1—A.honoka和格点三角形【计数】

2020牛客寒假算法基础集训营1—A.honoka和格点三角形【计数】链接

题目描述
honoka最近在研究三角形计数问题。
她认为,满足以下三个条件的三角形是“好三角形”。
1.三角形的三个顶点均为格点,即横座标和纵座标均为整数。
2.三角形的面积为 。
3.三角形至少有一条边和 轴或 轴平行。
honoka想知道,在平面中选取一个大小为 的矩形格点阵,可以找到多少个不同的“好三角形”?由于答案可能过大,请对 取模。
输入描述:
两个正整数和( 2\ ≤n,m≤10^9)(2 ≤n,m≤10
9

输出描述:
面积为1的格点三角形的数量,对 10^9+7 取模的结果。

示例1
输入

2 3

输出

6

说明
格点如下:

。 。 。
。 。 。
不妨设左下角座标为(1,1),右上角座标为到(3,2)。
那么三点座标可选:
(1,1)(1,2)(3,1)
(1,1)(1,2)(3,2)
(1,1)(2,2)(3,1)
(1,1)(3,1)(3,2)
(1,2)(2,1)(3,2)
(1,2)(3,1)(3,2)
所以共有6个。

示例2
输入

100 100

输出

7683984

说明
这里太小写不下啦。
备注:

可以把面积为 11 的“好三角形”分为两类分开统计:两条边和两个座标轴平行;只有一条边和某个座标轴平行。
(1)对于第一种情况,一定是 12 或者 21 的形式,一个 12 的矩形中含有4个不同的三角形,同理一个21的矩形中也含有4个不同的三角形
总数是 4*((n-2)(m-1)+(m-2)(n-1))

(2)对于第二种情况,可以分别统计底边为 2 、高为 1 和底边为 1 、高为 2 的情况。要注意底边靠近边界时的特殊讨论。
①对于底边为2,高为1的情况:

若底边和x轴平行,那么底边横向移动(指x轴水平移动,下同)有 n-2种可能,“对点”(指底边相对的点)的某一面选择有 n-2 种可能(某一面选择,指的是底边固定的情况,对点在一条直线上移动所做出的选择),而底边纵向移动有 m 种情况,其中有 (m-2)种情况对点可以选择两个面,2种情况对点只能选择一个面(当底边移动到格点阵边界的时候)。因此纵向移动折合为 2*(m-2)+2,即2*(m-1)
以上可计算为2*(m-1)(n-2)(n-2)

若底边和y轴平行,同理可推出 2*(n-1)(m-2)(m-2)
总数是2*(m-1)(n-2)(n-2)+2*(n-1)(m-2)(m-2)

②对于底边为1,高为2的情况,与①类似,若底边和x轴平行,那么底边横向移动(指x轴水平移动,确保了底为1)有 n-1种可能,对点”(指不在底边的另外一点,它确保了高为2)的某一面选择有 n-2 种可能(某一面选择,指的是底边固定的情况,对点在一条直线上移动所做出的选择),而底边纵向移动并且保证高为2,则有 (m-2)种情况对点可以选择,以上可计算为2*(n-1)(n-2)(m-2)

若底边和y轴平行,同理可推出 2*(m-1)(m-2)(n-2)
总数是2*(n-1)(n-2)(m-2)+ 2*(m-1)(m-2)(n-2)

综上所述“好三角形”计数为4*((n-2)(m-1)+(m-2)(n-1))+2*(m-1)(n-2)(n-2)+2*(n-1)(m-2)(m-2)+2*(n-1)(n-2)(m-2)+ 2*(m-1)(m-2)(n-2)

 #include<bits/stdc++.h> 
#include<iostream>
using namespace std;
const int mod=1e9+7;
int main()
{
	ios::sync_with_stdio(0);cin.tie(0);    //2-4牛客 A题 
	long long n,m;
	cin>>n>>m;
	long long a,b,c;
	a=4*((n-2)%mod*(m-1)%mod+(n-1)%mod*(m-2)%mod)%mod;
	b=2*((n-2)%mod*(n-2)%mod*(m-1)%mod+(n-1)%mod*(m-2)%mod*(m-2)%mod)%mod;
	c=2*((n-1)%mod*(n-2)%mod*(m-2)%mod+(n-2)%mod*(m-1)%mod*(m-2)%mod)%mod; 
	cout<<(a+b+c)%mod;
	} 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章