首页 > 其他 > 详细

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

时间:2019-11-12 15:03:07      阅读:80      评论:0      收藏:0      [点我收藏+]

洛谷 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;
}

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

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

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!