数三角形(codevs 3693)
题目描述 Description
给定一个n×m的网格,请计算三个点都在格点上的三角形共有多少个(三角形的三点不能共线)。下图为4×4的网格上的一个三角形。
输入描述 Input Description
输入一行,包含两个空格分隔的正整数m和n。
输出描述 Output Description
输出一个正整数,为所求三角形的数量。
样例输入 Sample Input
样例输入1:
1 1
样例输入2:
2 2
样例输出 Sample Output
样例输出1:
4
样例输出2:
76
数据范围及提示 Data Size & Hint
20%的数据满足1 ≤m,n≤ 10;
100%的数据满足1 ≤m,n≤ 1800。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/* long long 都爆,这数据也是没谁了 答案很明显是C((m+1)*(n+1),3)减去三个点在一条线的情况 对于(0,0)到(i,j)这条线,中间点的个数是gcd(i,j)-1, 和它斜率相同的线段有(n-i+1)*(m-j+1)条。 */ #include<cstdio> #include<iostream> #define LL unsigned long long #define M 2010 using namespace std; int gcd[M][M]; int get_gcd(int a,int b) { if(gcd[a][b])return gcd[a][b]; if(!b)return gcd[a][b]=a; return gcd[a][b]=get_gcd(b,a%b); } int main() { LL n,m; cin>>n>>m; n+=1;m+=1; LL ans=(n*m)*(n*m-1)/2*(n*m-2)/3; for(int i=0;i<=n;i++) for(int j=0;j<=m;j++) if(i||j) { LL t=(get_gcd(i,j)-1)*(n-i)*(m-j); if(!i||!j)ans-=t; else ans-=2*t; } cout<<ans; return 0; }
http://blog.csdn.net/zhb1997/article/details/38474795也有解释