显然问题求解可以转化:求可以构成多少个三角形等价于在网格中任选三点的方案数减去三点共线的方案数。网格中任选三点的方案数根据组合数易得。
现在考虑一下三点共线的方案数。
首先我们仍然容易得到三点都是横着与竖着的情况,接下来我们只需要考虑横着的三点共线的方案数即可。
枚举每个点 ,则 和 再与其他的一个点能共线的个数为 ,然后考虑考虑平行线,因为不是每个三点共线都会经过 , 类似处理,所以此处的结果要 .
注意,
参考代码:
#include <cstdio>
#define LL long long
LL N,M,Num,Ans;
LL Gcd(LL X,LL Y){
while(Y^=X^=Y^=X%=Y);return X;
}
int main(){
LL I,J,K;
scanf("%lld%lld",&N,&M);
N++,M++;Num=N*M;
Ans=(Num)*(Num-1)*(Num-2)/6;
for(I=1;I<N;I++){
for(J=1;J<M;J++){
K=Gcd(I,J);
if(K>=2){
Ans=(Ans-2*(K-1)*(N-I)*(M-J));
}
}
}
Ans-=N*M*(M-1)*(M-2)/6;
Ans-=M*N*(N-1)*(N-2)/6;
printf("%lld",Ans);
return 0;
}