洛谷P3166:https://www.luogu.org/problemnew/show/P3166
思路
用组合数求出所有的3个点组合(包含不合法的)
把横竖的3个点共线的去掉
把斜的3个点共线的去掉(枚举所有的矩阵把每个矩阵的对角线去掉)
每一条对角线可以取得首尾两点有(n-i)*(m-j)*2种方式可以选择
每一条对角线除了首尾两个点之外可以取到中间点有gcd(i,j)-1个 因此有对于每个条对角线有gcd(i,j)-1种要去掉(相似三角形)
代码
#include<iostream> using namespace std; #define maxn 1010 long long n,m,ans=1; long long gcd(long long a,long long b) { if(!b) return a; else return gcd(b,a%b); } long long C(int n,int m) { long long ret=1; for(int i=1;i<=m;i++) ret=ret*(n-i+1)/i; return ret; } int main() { cin>>n>>m; n+=1; m+=1; ans=C(n*m,3); if(n>=3) ans-=C(n,3)*m;//减去横竖的点 if(m>=3) ans-=C(m,3)*n; for(long long i=1;i<n;i++) for(long long j=1;j<m;j++) ans-=(n-i)*(m-j)*(gcd(i,j)-1)*2;//减去斜的点 cout<<ans; }