洛谷P3166 [CQOI2014]数三角形
题目描述
给定一个nxm的网格,请计算三点都在格点上的三角形共有多少个。下图为4x4的网格上的一个三角形。注意三角形的三点不能共线。
输入输出格式
输入格式:
输入一行,包含两个空格分隔的正整数m和n。
输出格式:
输出一个正整数,为所求三角形数量。
输入输出样例
输入样例#1:
2 2
输出样例#1:
View Code
76 数据范围 1
——————————————————————————————————————————————————————————————————————————————————
这道题呢不好直接求三角形个数,用全集-补集思想转化为求三点共线的数量。
全部的情况当然是C(n+m,3)然后就处理三点共线问题辣
最后枚举所有的斜率然后计算就好辣
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<cstdio> #include<cstring> #include<algorithm> #define LL long long using namespace std; int read(){ int ans=0,f=1,c=getchar(); while(c<'0'||c>'9'){if(c=='-') f=-1; c=getchar();} while(c>='0'&&c<='9'){ans=ans*10+(c-'0'); c=getchar();} return ans*f; } LL C(LL n,LL m){ LL ans=1; for(int i=n;i>n-m;i--) ans*=i; for(int i=m;i;i--) ans/=i; return ans; } int n,m,f[1007][1007]; int gcd(int a,int b){ if(f[a][b]) return f[a][b]; if(!b) return a; return f[a][b]=gcd(b,a%b); } int main() { n=read()+1; m=read()+1; LL sum=C(n*m,3); for(int i=-n+1;i<=n-1;i++) for(int j=0;j<=m-1;j++){ if(!j&&i<=0) continue; int k=gcd(abs(i),j); sum-=(LL)(k-1)*(n-abs(i))*(m-j); }printf("%lld\n",sum); return 0; }