洛谷P3166 [CQOI2014]数三角形

题目描述

给定一个nxm的网格,请计算三点都在格点上的三角形共有多少个。下图为4x4的网格上的一个三角形。注意三角形的三点不能共线。

输入输出格式

输入格式:

 

输入一行,包含两个空格分隔的正整数m和n。

 

输出格式:

 

输出一个正整数,为所求三角形数量。

 

输入输出样例

输入样例#1:
2 2
输出样例#1:
76


数据范围
1

——————————————————————————————————————————————————————————————————————————————————

这道题呢不好直接求三角形个数,用全集-补集思想转化为求三点共线的数量。

全部的情况当然是C(n+m,3)然后就处理三点共线问题辣

 

最后枚举所有的斜率然后计算就好辣

#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;
}
View Code

 

 

posted @ 2017-08-02 23:11  友人Aqwq  阅读(205)  评论(0编辑  收藏  举报