洛谷 P3166 [CQOI2014]数三角形 BZOJ 3505 [Cqoi2014]数三角形

时间:2019-11-12
本文章向大家介绍洛谷 P3166 [CQOI2014]数三角形 BZOJ 3505 [Cqoi2014]数三角形,主要包括洛谷 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 \times C_{m}^{3}$

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

3.三点不过斜线:如何判断斜线,这就是这道题的难点所在,分析后我们可以发现一个问题,对于一个$(x \times 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\n", ans);
    return 0;
}

原文地址:https://www.cnblogs.com/littleseven777/p/11841296.html