zoukankan      html  css  js  c++  java
  • [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;
    }
    
    
  • 相关阅读:
    java编程继承的第一原则
    Java基本语法总结
    java 语言实现的随机数生成算法
    java实现微公众平台自定义菜单
    使用Java调用谷歌搜索
    Java 语言实现的随机数生成算法
    浅谈Java中的instanceof关键字
    Java 编程基础 类和继承总结
    异常封装提高Java代码质量
    CSS-font
  • 原文地址:https://www.cnblogs.com/PPXppx/p/10362950.html
Copyright © 2011-2022 走看看