zoukankan      html  css  js  c++  java
  • [BZOJ][CQOI2014]数三角形

    Description

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

    注意三角形的三点不能共线。

    Input

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

    Output

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

    Sample Input

    2 2

    Sample Output

    76

    数据范围
    1<=m,n<=1000
     
     

          因为就在做这道题之前看的一道题……下意识以为只有直线和对角线的情况,然后搞成O(n)算法似乎自己比其他写题解的神犇厉害??事实上我错了,,,orz(雾(跪地(无奈(orz(%%%(逃

          首先,显然的,不考虑三点共线共有C(n*m,3)种方法,所以问题转化为三点共线有几种情况?

          在(x1,y1) (x2,y2)两点构成的线段(不含端点)上有gcd(x1-x2,y1-y2)-1个整点。

          所以我们可以在logn的时间求出一条线段中的整点个数,但枚举两个点显然要超时,所以我们只枚举一个点的坐标,它与(0,0)显然构成了唯一的一条线段,然后我们发现这条线段其实可以移动,所以就将一条线段的解*(n-x)*(m-y)

          相减就得到答案啦~~

    #include<cstdio>
    #include<algorithm>
    #define ll long long
    using namespace std;
    ll n,m;
    ll gcd(ll a,ll b){
        return b?gcd(b,a%b):a;
    }
    int main(){
        scanf("%lld%lld",&n,&m);
        n++;m++;
        ll ans=(n*m)*(n*m-1)*(n*m-2)/6;    
        for(int i=0;i<n;i++)
        for(int j=0;j<m;j++){
            ll c;
            if(!i)c=j-1;
            if(!j)c=i-1;
            if(i&&j)c=gcd(i,j)-1;
            if(c<0)c=0;
            if(i&&j)ans-=c*(n-i)*(m-j)*2;else ans-=c*(n-i)*(m-j);
        }
        printf("%lld",ans);
    }
  • 相关阅读:
    关于oracle的导入数据流程,以及错误解决
    解决 lombok 和 freemarker 下载慢问题 以及安装方法
    解决maven项目没有Maven Dependencies
    将maven仓库改为阿里仓库
    Dos攻击和校网渗透
    KaliLinux切换python版本
    Kali国内更新源
    linux安装jdk(.rpm)
    Centos 关于 mysql 命令
    Linux删除命令
  • 原文地址:https://www.cnblogs.com/sffey/p/6916999.html
Copyright © 2011-2022 走看看