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

传送门


题目描述

honoka最近在研究三角形计数问题。
她认为,满足以下三个条件的三角形是“好三角形”。

  1. 三角形的三个顶点均为格点,即横坐标和纵坐标均为整数。
  2. 三角形的面积为 。
  3. 三角形至少有一条边和 轴或 轴平行。
    honoka想知道,在平面中选取一个大小为 的矩形格点阵,可以找到多少个不同的“好三角形”?由于答案可能过大,请对 取模。

输入描述:

两个正整数和 2   n , m 1 0 9 ( 2\ ≤n,m≤10^9)


输出描述:

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


输入

2 3
100 100


输出

6
7683984


说明

  • 格点如下:
    * * *
    * * *
  • 不妨设左下角坐标为(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个。

题解

  • 可以把面积为 1 1 的“好三角形”分为两类分开统计:两条边和两个坐标轴平行;只有一条边和某个坐标轴平行。
    对于第一种情况,一定是 1 2 1*2 或者 2 1 2*1 的形式,一个 1 2 1*2 的矩形中含有 4 4 个不同的三角形。总数是 4 ( ( n 2 ) ( m 1 ) + ( m 2 ) ( n 1 ) ) 4*((n-2)*(m-1)+(m-2)*(n-1))
  • 对于第二种情况,可以分别统计底边为 2 2 、高为 1 1 和底边为 1 1 、高为 2 2 的情况。要注意底边靠近边界时的特殊讨论。
    • ①对于底边为 2 2 ,高为 1 1 的情况:
      若底边和 x x 轴平行,那么底边横向移动(指 x x 轴水平移动,下同)有 n 2 n-2 种可能,“对点”(指底边相对的点)的某一面选择有 n 2 n-2 种可能(某一面选择,指的是底边固定的情况,对点在一条直线上移动所做出的选择),而底边纵向移动有 m m 种情况,其中有 ( m 2 ) (m−2) 种情况对点可以选择两个面, 2 2 种情况对点只能选择一个面(当底边移动到格点阵边界的时候)。因此纵向移动折合为 2 ( m 2 ) + 2 2*(m-2)+2 ,即 2 ( m 1 ) 2*(m-1)
      以上可计算为 2 ( m 1 ) ( n 2 ) ( n 2 ) 2*(m-1)*(n-2)*(n-2)
      若底边和 y y 轴平行,同理可推出 2 ( n 1 ) ( m 2 ) ( m 2 ) 2*(n-1)*(m-2)*(m-2)
      在这里插入图片描述
    • ②对于底边为 1 1 ,高为 2 2 的情况,推理方法和上面类似,请选手们自行推理。
  • c f 1500 参考cf难度分:1500
  • 最后得到三类分别为:
    l l ll a n s 1 = 4 ( ( n 2 ) ( m 1 ) + ( m 2 ) ( n 1 ) ) ; ans1 = 4 * ((n - 2) * (m - 1) + (m - 2) * (n - 1));
    l l ll a n s 2 = 2 ( m 1 ) ( n 2 ) ( n 2 )                + 2 ( n 1 ) ( m 2 ) ( m 2 ) ; ans2 = 2 * (m - 1) * (n - 2) * (n - 2) \\\ \ \ \ \ \ \ \ \ \ \ \ \ \ + 2 * (n - 1) * (m - 2) * (m - 2);
    l l ll a n s 3 = ( n 1 ) ( n 2 ) ( 2 ( m 4 ) + 4 )              + ( m 1 ) ( m 2 ) ( 2 ( n 4 ) + 4 ) ; ans3 = (n - 1) * (n - 2) * (2 * (m - 4) + 4) \\\ \ \ \ \ \ \ \ \ \ \ \ + (m - 1) * (m - 2) * (2 * (n - 4) + 4);

AC-Code

#include <bits/stdc++.h>
using namespace std;
#define ll long long

const ll M = 1e9 + 7;
ll ans = 0, n, m;
int main() {
	cin >> n >> m;
	ans += (((2 * m * n - 3 * n - 3 * m + 4) % M) * ((2 * m + 2 * n - 4) % M)) % M;
	cout << ans;
}
发布了157 篇原创文章 · 获赞 99 · 访问量 9828

猜你喜欢

转载自blog.csdn.net/Q_1849805767/article/details/104174259