[CQOI2014]数三角形

Posted ppxppx

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[CQOI2014]数三角形相关的知识,希望对你有一定的参考价值。

传送门

题意:给定一个nxm的网格,计算三点都在格点上的三角形共有多少个?注意三角形的三点不能共线.

分析:nxm的网格有tot=(n+1)*(m+1)个格点,暴力算出所有方案数(C_{tot}^3),然后减去平行于x轴和y轴的共线三角形((n+1)*C_{m+1}^3)((m+1)*C_{n+1}^3),最后减去倾斜直线上的共线三角形.

这个比较麻烦,我先直接给出式子,然后再来具体分析,因为懒得画图(其实是不会),所以就只能耐心地口胡(2*(gcd(i,j)-1)*(n+1-i)*(m+1-j))

乘2:矩形具有对称性,所以倾斜直线也是对称的(就是说把倾斜直线看作一种是自左上往右下,另一种是自右上往左下,这两种情况是相同的,所以我们下面可以只讨论一种情况)

乘gcd(i,j)-1:首先要知道一个结论,对于点(a,b)和(x,y)连成的线段而言(其中a>x,b>y),在它们中间有gcd(a-x,b-y)-1个整点(自己画几个图就能发现这个规律了),然后我们不妨以左上角(0,0)点为枚举矩形的左上角顶点,所以我们只需要枚举右下角顶点(i,j)就可以了.根据结论这两个点连成的线段中间有gcd(i-0,j-0)-1个格点.

对于(n*m)的网格而言,像上述那样枚举矩形的话,一共有(n+1-i)*(m+1-j)个矩形(这里不明白也画几个图吧)

int gcd(int x,int y){
    if(y==0)return x;
    return gcd(y,x%y); 
}
int main(){
    int m=read(),n=read();
    m++;n++;//为了方便,这里直接都+1了
    int tot=m*n;
    long long ans=1LL*tot*(tot-1)*(tot-2)/6-1LL*m*n*(n-1)*(n-2)/6-1LL*n*m*(m-1)*(m-2)/6;
    for(int i=1;i<n;i++)
        for(int j=1;j<m;j++)
            ans-=1LL*2*(gcd(i,j)-1)*1LL*(n-i)*(m-j); 
    printf("%lld
",ans);
    return 0;
}

以上是关于[CQOI2014]数三角形的主要内容,如果未能解决你的问题,请参考以下文章

3505: [Cqoi2014]数三角形

BZOJ3505[Cqoi2014]数三角形 组合数

BZOJ 3505 [Cqoi2014]数三角形

bzoj3505 [Cqoi2014]数三角形

P3166 [CQOI2014]数三角形(组合数学)

BZOJ-3505: [Cqoi2014]数三角形 (容斥原理+排列组合)