zoukankan      html  css  js  c++  java
  • UPC-3843 数三角形(容斥原理+gcd+组合数)

    题目描述
    给定一个nxm的网格,请计算三点都在格点上的三角形共有多少个。下图为4x4的网格上的一个三角形。
    这里写图片描述

    注意:三角形的三点不能共线。n×m的网格共有(n+1)×(m+1)个格点。
    输入
    输入一行,包含两个空格分隔的正整数m和n(1<=m,n<=1000)。
    输出
    输出一个正整数,为所求三角形数量。
    样例输入
    2 2
    样例输出
    76

    容斥原理,先算所有格子中任意取3点的数量,减去三点共线的数量
    有n*m个格子,那么就有(n+1)*(m+1)个交点
    于是对于所有(n+1)(m+1)=x个交点任意取三点作为三角形三点即x(x-1)*(x-2)/1*2*3【组合数】
    组合数C(3,x),从x个点中任意取三个作为三角形三点
    首先计算所有点取3点的数量,组合数求,接着减去同在一行和一列的所有情况,那么就是n+1长度的一列上有C(3,K)的种类,总共有m+1列这样的长度,同样m+1长度的n+1行也是一样

    除去横向和纵向,接下来是斜着的重复数量,首先从源点0,0开始以不同斜率连接除边界外的每一个点,求GCD(i,j)-1得到在0,0和i,j之间有多少可选点构成三点一线

    此处以0,0作为源点,i,j作为一个小的矩形范围内出现重复的区域,以i,j为另一定点,取两定点中间多个动点作为第三个点,有gcd(i,j)-1的匹配数量三点一线

    算出以左上角矩形为基点的所有斜向共线可能后,以当前i,j小矩形为一范围,向下平移(n+1-i)个单位得到不同种数,向右平移(m+1-j)个单位得到同样大小的矩形在其他基点的种数

    相乘后得到该大小矩形在所有区域的不重复共线可能,然后*2,表示左斜和右斜两种情况

    减去所有共线可能后得到最终结果

    #include<stdio.h>
    #include<string.h>
    long long sum(long long x)
    {
        return x*(x-1)*(x-2)/6;
    }
    long long gcd(int x,int y)///GCD写错了一直查不到错
    {
        while(y!=0)
        {
            long long c=y;
            y=x%y;
            x=c;
        }
        return x;
    }
    int main()
    {
        long long n,m;///输入n*m个格子,其中有n+1行,m+1列
        while(scanf("%lld%lld",&n,&m)!=EOF)
        {
            long long ans=sum((n+1)*(m+1))-(m+1)*sum(n+1)-(n+1)*sum(m+1);
            for(int i=1;i<=n;i++)
            {
                for(int j=1;j<=m;j++)///逐个减去不会重复或少减
                {
                    ans-=2*(gcd(i,j)-1)*(m+1-j)*(n+1-i);
                }
            }
            printf("%lld
    ",ans);
        }
    }
    
  • 相关阅读:
    Spring MVC之视图呈现
    Spring MVC之HandlerMap 初始化
    Spring MVC之DispatcherServlet请求处理
    合成模式
    缺省适配器
    适配器模式
    原始模型
    克隆 和 比较
    建造模式
    线段树
  • 原文地址:https://www.cnblogs.com/kuronekonano/p/11135839.html
Copyright © 2011-2022 走看看