zoukankan      html  css  js  c++  java
  • 洛谷 P3166 [CQOI2014]数三角形 BZOJ 3505 [Cqoi2014]数三角形

    洛谷 P3166 [CQOI2014]数三角形

    BZOJ 3505 [Cqoi2014]数三角形

    题目链接:洛谷 P3166 [CQOI2014]数三角形 BZOJ 3505 [Cqoi2014]数三角形

    算法标签: 组合数学最大公约数

    题目

    题目描述

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

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

    输入格式

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

    输出格式

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

    输入输出样例

    输入 #1

    2 2
    

    输出 #1

    76
    

    说明/提示

    数据范围

    bzoj上是1<=m,n<=1000

    题解:

    组合数学

    首先对于这道题的读入,n和m是从0开始计算的,为了方便处理,不妨将n与m都++。

    我们可以先考虑去枚举每一个三角形,很显然是做不到的。

    那么我们可以换一种思路,我们可以确定的是每一个三角形一定有三个点,并且这三个点不共线。

    对于一定有三个点,很显然我们可以得到总答案:(ans~=~C_{n*m}^{3})

    那么对于三点不共线,我们现在就要考虑以下的情况:

    1.三点不共横线:很显然,我们枚举每一条横边,在上边任选三个点,这样的三个点都是不合法的,又因为有n条横边,所以(ans~-=~n imes C_{m}^{3})

    2.三点不共竖线:同上,枚举每一条竖边,任选三点除去,所以(ans~-=~m imes C_{n}^{3})

    3.三点不过斜线:如何判断斜线,这就是这道题的难点所在,分析后我们可以发现一个问题,对于一个((x imes y))的网格矩形,从最左上角点到最右下角点的直线会经过(gcd(x,y)-1)个格点(不包含起点和中点),同理从最右上角点到最左下角点也会经过(gcd(x, y)-1)个格点,那么我们只需要枚举所有的矩形,删去这些情况即可:(ans~-=~(n-i)*(m-j)*(gcd(i,j)-1)*2)

    最终得到的ans就是答案。

    !!!注意:这道题的数据需要开(long long)

    AC代码

    #include <bits/stdc++.h>
    
    using namespace std;
    
    typedef long long ll;
    
    ll n, m, ans;
    
    ll gcd(ll a,ll b)
    {
    	if (b == 0)
    		return a;
    	return gcd(b, a % b);
    }
    int main()
    {
    	scanf("%lld%lld", &m ,&n);
    	n ++ ;
    	m ++ ;
    	ans = (n * m) * (n * m - 1) * (n * m - 2) / (1 * 2 * 3);
    	ans -= n * m * (m - 1) * (m - 2) / (1 * 2 * 3);
    	ans -= m * n * (n - 1) * (n - 2) / (1 * 2 * 3);
    	for (ll i = 2; i < n; i ++ )
    		for (ll j = 2; j < m; j ++ )
    		{
    			ans -= (n - i) * (m - j) * (gcd(i, j) - 1) * 2;
    		}
    	printf("%lld
    ", ans);
    	return 0;
    }
    
  • 相关阅读:
    CSS学习1
    三个和尚没水喝阅读笔记
    Javascript学习1

    mv 批量
    emacs 大小写转换
    too many open files
    成都定房
    有关重定向
    postgresql 数据库
  • 原文地址:https://www.cnblogs.com/littleseven777/p/11841296.html
Copyright © 2011-2022 走看看