1655:数三角形
时间限制: 1000 ms 内存限制: 524288 KB【题目描述】
给定一个 n×m 的网格,请计算三点都在格点上的三角形共有多少个。下图为 4×4 的网格上的一个三角形。
注意:三角形的三点不能共线。
【输入】
输入一行,包含两个空格分隔的正整数 m 和 n。
【输出】
输出一个正整数,为所求三角形数量。
【输入样例】
2 2
【输出样例】
76
【提示】
数据范围与提示:
对于所有数据,1≤m,n≤1000。
sol:肯定是算不能构成三角形的方案数比较容易。
总方案数就是C(n*m,3)
不能构成的有两种情况
1)三个点都在同一条与水平面平行或垂直的线上 C(n,3)*m+C(m,3)*n
2)对于一条任意长度的斜线,设其两端坐标为(1,1) (a,b),那么斜线上格点的个数就是gcd(a-1,b-1)+1,在整个矩形中这样的斜线会有(n-a+1)*(m-b+1)条,但是直接在这条斜线上任取三个点会有重复,所以钦定两个端点必须取,中间任取一个点
注意有斜线有两个方向,这样的要减两倍
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
#include <bits/stdc++.h> using namespace std; typedef long long ll; inline ll read() { ll s=0; bool f=0; char ch=' '; while(!isdigit(ch)) { f|=(ch=='-'); ch=getchar(); } while(isdigit(ch)) { s=(s<<3)+(s<<1)+(ch^48); ch=getchar(); } return (f)?(-s):(s); } #define R(x) x=read() inline void write(ll x) { if(x<0) { putchar('-'); x=-x; } if(x<10) { putchar(x+'0'); return; } write(x/10); putchar((x%10)+'0'); return; } #define W(x) write(x),putchar(' ') #define Wl(x) write(x),putchar('\n') ll n,m; inline ll gcd(ll x,ll y) { return (!y)?(x):(gcd(y,x%y)); } int main() { ll i,j,ans=0,Sum=0; n=read()+1; m=read()+1; ans=(n*m)*(n*m-1)*(n*m-2)/6; ans-=m*n*(n-1)*(n-2)/6; ans-=n*m*(m-1)*(m-2)/6; for(i=2;i<=n;i++) { for(j=2;j<=m;j++) { ll tmp=gcd(i-1,j-1)+1; if(tmp>2) Sum+=(tmp-2)*(n-i+1)*(m-j+1); } } Wl(ans-(Sum<<1)); return 0; } /* input 2 2 output 76 input 6 9 output 52758 */