zoj 3647 Gao the Grid (求三角形的个数,困难)

来源:互联网 发布:重返德军总部 知乎 编辑:程序博客网 时间:2024/05/22 01:28

n * m grid as follow:

a n*m grid(n=4,m=3)

Count the number of triangles, three of whose vertice must be grid-points.
Note that the three vertice of the triangle must not be in a line(the right picture is not a triangle).

a triangle not a triangle

Input

The input consists of several cases. Each case consists of two positive integers n and m (1 ≤ nm ≤ 1000).

Output

For each case, output the total number of triangle.

Sample Input

1 12 2

Sample Output

476

hint

hint for 2nd case: C(9, 3) - 8 = 76

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4837
求一个格子图里最多有多少不同的三角形(位置不同也算)
这题要倒着来思考。先求出所有3个点的组合数,再减去其中不符合的(三点共线)——这个地方不容易思考。本来想直接枚举的,但不可行。经过大神指导明白了一个定理:告诉你长和宽,求格子图里与这条线段(斜边)共线的点有多少个:gcd(i,j)-1 
然后这条线段可以放的位置有(n+1-i)*(m+1-j)种。因为有同样的对角线(中心对称)所以*2.

#include<iostream>#include<algorithm>#include<string>#include<map>#include<vector>#include<cmath>#include<string.h>#include<stdlib.h>#include<cstdio>#include <ctime>#include <cstdlib> #define ll long longusing namespace std; long long C(int n,int m)  {      long long res=1;      if(n<m) return 0;      if(n-m<m) m=n-m;      int i,j;      for(i=0,j=1;i<m;i++)      {          res*=(n-i);          for(;j<=m&&res%j==0;j++) res/=j;      }      return res;  } int gcd(int a,int b){        return b?gcd(b,a%b):a;}int main(){ll n,m;while(cin>>n>>m){ll s=C((n+1)*(m+1),3)-C(m+1,3)*(n+1)-C(n+1,3)*(m+1);for(int i=2;i<=n;++i){for(int j=2;j<=m;++j){s-=(gcd(i,j)-1)*(n+1-i)*(m+1-j)*2;}}cout<<s<<endl;}return 0; } 


0 0