数三角形

链接

https://www.acwing.com/problem/content/1312/

题目

给定一个 n×m 的网格,请计算三点都在格点上的三角形共有多少个。

下图为 4×4 的网格上的一个三角形。

注意:三角形的三点不能共线。

输入格式
输入一行,包含两个空格分隔的正整数 m 和 n。

输出格式
输出一个正整数,为所求三角形数量。

数据范围
1≤m,n≤1000
输入样例:
2 2
输出样例:
76

思路

正难则反。直接求解合法的个数不好求,可以反过来求不合法的个数。从图中选出三个点的选法有(C((n+1)×(m+1),3)),只有当三个点在一条直线上才会不合法。三点共线的可能:
 1.垂直:(C(m+1,3)×(n+1))
 2.水平:(C(n+1,3)×(m+1))
 3.倾斜:首先枚举一个底边长度为i,高度为j的三角形,共有((n-i+1)×(m-j+1))种。其中两个点在端点,另一个在斜边中间,第三个点有(gcd(i,j)-1)种。((n-i+1)×(m-j+1)×(gcd(i,j)-1))

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
LL C(int n){
    return (LL)n*(n-1)*(n-2)/6;
}
int main(){
    int n,m;
    cin>>n>>m;
    n++,m++;
    LL ans=C(n*m)-n*C(m)-m*C(n);
    n--,m--;
    for(int i=1;i<=n;++i){
        for(int j=1;j<=m;++j){
            ans-=2LL*(n-i+1)*(m-j+1)*(__gcd(i,j)-1);
        }
    }
    cout<<ans<<endl;
    return 0;
}
原文地址:https://www.cnblogs.com/jjl0229/p/12741419.html