题目概述
求 n×m 网格中的三角形个数。
解题报告
首先肯定是用总方案数 (n3) 减去不合法的方案数要方便很多。但是怎么求不合法(三点共线)的方案数?
有个结论是横长为
x
纵长为
那么只要枚举 x,y ,然后算出共线三角形的方案数 gcd(x,y)−1 ,再把这条线段放入网格(共有 (n−x+1)(m−y+1) 种方案)就行了。
示例程序
#include<cstdio>
using namespace std;
typedef long long LL;
int n,m;LL ans;
#define C(x) ((LL)(x)*((x)-1)*((x)-2)/6)
int gcd(int a,int b) {if (!b) return a;return gcd(b,a%b);}
int main()
{
freopen("program.in","r",stdin);
freopen("program.out","w",stdout);
scanf("%d%d",&m,&n);n++;m++;ans=C(n*m);
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++) if (i>1||j>1)
{
LL now=(LL)(n-i+1)*(m-j+1)*(gcd(i-1,j-1)-1);
ans-=now;if (i-1&&j-1) ans-=now;
}
return printf("%lld\n",ans),0;
}