链接
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;
}