给定一个 n×m 的网格,请计算三点都在格点上的三角形共有多少个。
下图为 4×4 的网格上的一个三角形。
注意:三角形的三点不能共线。
输入格式:
输入一行,包含两个空格分隔的正整数 m 和 n。
输出格式:
输出一个正整数,为所求三角形数量。
题解:首先n+1,m+1,题目给的是网格数,转换为网格点数 ,首先求出C(nm,3),这样就是总共任选三个点的方案数,然后减去共线的方案数就是答案。
共线的分为三种:
1、竖直线上的是mC(n,3),代表每列任选三个,总共m列
2、水平线上的是nC(m,3),代表每行任选三个,总共n行
3、是倾斜的线段,当然,有斜率大于0的也有斜率小于0的,这两种情况的数量是一样的,只求斜率大于0的就行,斜率大于0的可以枚举构成这条线段的另外两条边来求,比如这条线段可以和底的长度为i,高的长度为j构成一个直角三角形(左下角端点和右上角端点在整点上),这么这俩点之间的整点个数就是gcd(i,j),然后这种三角形的个数总共有(n-i)(m-j)个,所以答案就是枚举ij,2gcd(i,j)(n-i)*(m-j).
题目:https://www.acwing.com/activity/content/11/可能需要报课才能做
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <ctime>
#include <vector>
#include <stack>
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 s=C(n*m)-n*C(m)-m*C(n);
for(int i=1; i<=n; i++)
{
for(int j=1; j<=m; j++)
{
s-=(ll)2*(__gcd(i,j)-1)*(n-i)*(m-j);
}
}
cout<<s<<endl;
return 0;
}