題目意思:在一個n*m個方格中(頂點有(n+1)*(m+1)個),求所有三角形數,即三點不共線的所有情況。 題解:令所有點的個數為t,用c[t,3]來枚舉所有情況,用總數扣去所有三點共線數就是所求的三角形數。那麼在求三點共線的情況時,水平和垂直的情況讀者自己考慮。對於傾斜的情況,先枚舉兩端的端點,如圖,在一個6*10的方格中選4*4的兩個端點,其中可構成三點花線的另一點的個數為最大公約數gcd(4,4) -1.如圖中的三個點,然後用乘於剩下的倍數(6-4+1)*(10-4+1),再乘於2(傾斜時有右上,右下兩種情況).然後依次枚舉所有的矩形,求出所有三點共線的情況。於是所有情況減三點共線情況就是答案了。 代碼如下: [cpp] /* * File: main.cpp * Author: ssslpk * * Created on September 29, 2012, 12:20 PM */ #include <cstdlib> #include<math.h> #include<stdio.h> #define int64 long long int using namespace std; #define N 1002 int64 f[N][N]; int gcd(int a,int b){return b? gcd(b,a%b): a;} void init() { for(int i=1;i<=1000;i++) { for(int j=i;j<=1000;j++) { int d=gcd(i,j); f[i][j]=f[j][i]=(int64)(d-1); } } } int main() { int64 n,m; init(); while(scanf("%lld%lld",&n,&m)!=EOF) { int64 sum=0; for(int64 i=1;i<=n;i++) { www.2cto.com for(int64 j=1;j<=m;j++) { sum+=f[j][i]*2*(n-i+1)*(m-j+1); } } if(n>=2)sum+=(n+1)*(n)*(n-1)/6*(m+1); if(m>=2)sum+=(m+1)*(m)*(m-1)/6*(n+1); int64 t=(n+1)*(m+1); int64 num; if(t%3==0) { if((t-1)%2==0)num=t/3*(t-1)/2*(t-2); else num=t/3*(t-2)/2*(t-1); } else if((t-1)%3==0) { if(t%2==0) num=t/2*(t-1)/3*(t-2); else num=(t-1)/6*(t-2)*t; } else { if((t-1)%2==0) num=(t-1)/2*(t-2)/3*t; else num=(t)/2*(t-2)/3*(t-1); } // printf("sum: %lld\n",sum); printf("%lld\n",num-sum); } return 0; }