此题就是求格点中三角形的个数。
就是找出三点不共线的个数。
n*m的矩形中有(n+1)*(m+1)个格点。
选出三个点的总个数为:C((n+1)*(m+1),3).
减掉共线的情况就是答案了。
首先是水平和垂直共线的情况:C(n+1,3)*(m+1)+C(m+1,3)*(n+1);
然后斜的共线的情况就是枚举矩形。
斜着共线的三点用枚举法n*m的矩形,对角两个点中间共有gcd(m,n)-1个点,两条对角线,所以数量*2,大矩形里共有(N-n+1)*(M-m+1)个的矩形,一并去除
1 #include<stdio.h> 2 #include<iostream> 3 #include<string.h> 4 #include<algorithm> 5 using namespace std; 6 7 int gcd(int a,int b) 8 { 9 if(b==0)return a; 10 return gcd(b,a%b); 11 } 12 long long Com(int n,int r) 13 { 14 if(n<r)return 0;//这个一定要 15 if(n-r<r)r=n-r; 16 int i,j; 17 long long ret=1; 18 for(i=0,j=1;i<r;i++) 19 { 20 ret*=(n-i); 21 for(;j<=r&&ret%j==0;j++)ret/=j; 22 } 23 return ret; 24 } 25 int main() 26 { 27 int n,m; 28 while(scanf("%d%d",&n,&m)!=EOF) 29 { 30 long long ans=Com((n+1)*(m+1),3);//选三个点的所有组合数 31 for(int i=2;i<=n;i++) 32 for(int j=2;j<=m;j++) 33 { 34 ans-=(long long)(gcd(i,j)-1)*(n-i+1)*(m-j+1)*2; 35 } 36 ans-=Com(n+1,3)*(m+1); 37 ans-=Com(m+1,3)*(n+1); 38 printf("%lld\n",ans);//ZOJ用lld,不能用I64d 39 } 40 return 0; 41 }
时间: 2024-10-30 01:26:06