3505: [Cqoi2014]数三角形

来源:互联网 发布:vb 删除文件 编辑:程序博客网 时间:2024/05/17 22:55

题目链接

题目大意:给一张m*n的网格,问这里面以网格为顶点的三角形有多少个

题解:坐标从0开始,所以有(n+1)*(m+1)个点,输入后n++,m++

不考虑共线的话是C3nm,然后需要减去横竖斜三种共线
横竖明显是nC3mmC3n

下面考虑斜共线

结论:(0,0)(i,j)连线上整点的个数为gcd(i,j)+1(包括(0,0)(i,j))

固定点(0,0),枚举点(i,j),这样就确定了斜率k,只需要统计k为正的即可(负的可以通过翻转,0和不存在已经计算过了),考虑所成线段,中间有gcd(i,j)1个点

乘上(n-i)*(m-j),即通过平移能找到多少条这样的线段

有两种情况:一种是枚举的(0,0)-(i,j),即从左下角->右上角,还有一种(i,0)->(0,j),即从右下角->左上角,这两种情况是相同的,最后要乘2

我的收获:思考方向

#include <cstdio>  #include <cstring>  #include <cstdlib>  #include <cmath>  #include <iostream>  #include <algorithm>  using namespace std;  int n,m;long long ans;  long long C(int x){return (long long)x*(x-1)*(x-2)/6;}  void work(){    ans=C(n*m)-C(n)*m-C(m)*n;    for(int i=1;i<n;i++)          for(int j=1;j<m;j++)            ans-=2ll*(__gcd(i,j)-1)*(n-i)*(m-j);    printf("%lld\n",ans);  }void init(){    cin>>n>>m;n++;m++;} int main()  {      init();    work();    return 0;  }