Gao the Grid ZOJ 3647 数三角形

首先从所有的点中选3个点用来画三角形,一共有ans = C((n+1)*(m+1),3)种,然后减去三点共线的情况,三点水平和垂直共线很好考虑,ans -= (n+1)*C(m+1,3)

ans -= (m+1)*C(n+1,3).

然后针对斜线的情况,用枚举法。

先考虑如下的情况:

假设有一条过原点(0,0)和点(x0,y0)的线段,其中x0,y0均为正整数,那么这条线段上有多少个整数点呢。整数点就是坐标为(x,y)的点,其中x,y均为整数 。

答案上gcd(x0,y0)+1,下面证明:

这条线段的方程如下:y = k * x ,其中k = y0/x0. (x>=0 && x <= x0)

那么设y0分解为y0 = p1 * p2  ```` pk

x0的分解为x0 = q1*q2*q3````qs其中pi,qi均为素数

不妨设p1= q1,p2=q2,```pt =qt.剩下的pi和qj互素(i=t+1,```k,j=t+1,s),显然,p1*p1*```*pt就是gcd(x0,y0)(也就是x0 和 y0 的最大公约数)。

那么y  = k *x,当x取值为q(t+1)*q(t+2)*```*q(s),也就是x0/gcd(x0,y0)时,y为小于y0的整数,令d = x0/gcd(x0,y0),x取值为0*d,1*d,2*d ,```` gcd(x0,y0)*d,y都会是>=0,<=y0的整数,而这样选择的x也是>=0,<=x0的整数,所有在这条线段上一共有gcd(x0,y0)个整数点。由此得证。

这样的话,选定两个整数点(两整数点不在同一水平线或垂直线上,只考虑斜线的情况),再在这两个点组成的线段上另选一个点和这个点组成伪三角形,这样的伪三角形有多少个。

答案是,自己好好想想,呵呵,然后先列举斜率为正的斜线,然后发现斜率为负的斜率与之对称,所以斜率为正的斜线的伪三角形的个数*2即可

贴代码:

View Code
 1 #include <iostream>
 2 #include <cstdio>
 3 using namespace std;
 4 typedef long long LL;
 5 int gcd(int a,int b)
 6 {
 7     return b==0 ? a : gcd(b,a%b);
 8 }
 9 LL pc3(LL x)
10 {
11     LL y;
12     y = x*(x-1)*(x-2)/6;
13     return y;
14 }
15 int main()
16 {
17     int  n,m;
18     while(~scanf("%d%d",&n,&m))
19     {
20         LL ans = pc3((n+1)*(m+1));
21         ans -= (m+1)*pc3(n+1);
22         ans -= (n+1)*pc3(m+1);
23         for(int i=2; i<=n; ++i)
24         {
25             for(int j=2; j<=m; ++j)
26             {
27                 ans -= (long long int )(gcd(i,j)-1)*(n+1-i)*(m+1-j)*2;
28             }
29         }
30         cout<<ans<<endl;
31     }
32     return 0;
33 }
原文地址:https://www.cnblogs.com/allh123/p/3022499.html