【题解】AcWing 1390.通电围栏

题目传送门

题目描述

农夫约翰的牧场可以看作是一个二维平面。

约翰为了方便看管他养的牛,构建了一个三角形的通电围栏。

他希望他的奶牛都在围栏围起的区域内活动。

三角形围栏的三个顶点位置坐标分别为 (0,0),(n,m),(p,0),该围栏由三个顶点两两相连而成。

平面上,所有位于三角形围栏内部(不包括边)且横纵坐标都为整数的点上都可以放置一头奶牛。

请问,围栏中最多可以放置多少头奶牛。

输入格式

共一行,包含三个整数 n,m,p。

输出格式

输出一个整数,表示可放置的牛的最大数量。

数据范围

0≤n<32000,
0<m<32000,
0<p<32000

输入样例:

7 5 10

输出样例:

20

算法1

(暴力?模拟) (O(n))

就是把每个x的三角形三条线所对的y值算出,然后想想自己怎么做的,就是统计y1到y2点有几个,
这边也没有特别的暴力,比较完全暴力是(O(n^2))时间会超,所以运用简单的数学知识中的斜率来做就好。

这里需要注意的主要是n与p的关系
n < p 的时候下面的线是k = 0 的线
n > p 的时候是要求的两条线之间的点,就要相减了

还有两点注意点

  1. 当这个点算出刚好是整点的情况
  2. double的精度误差

C++ 代码

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>

using namespace std;

typedef long long LL;

int n, m, p;
double k1, k2, b2;

inline int get_cnt(double x)
{
    if(p > n)
    {
        if(x < n) return (int)(k1 * x - 1e-8);
        return (int)(k2 * x + b2 - 1e-8);
    }
    if(x < p) return (int)(k1 * x - 1e-8);
    return (int)(k1 * x - 1e-8) - (int)(k2 * x + b2 + 1e-8); // l2: (- 1e-8) x
}

int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cin >> n >> m >> p;
	k1 = 1.0 * m / n, k2 = 1.0 * m / (n - p), b2 = - k2 * p;
// 	cout << k1 << ' ' << k2 << ' ' << b2 << endl;
	LL res = 0;
	for(int i = 1; i < max(p, n); i ++)
	{
	    res += get_cnt(i);
	   // cout << get_cnt(i) << endl;
	}
	cout << res << endl;
	return 0;
}
原文地址:https://www.cnblogs.com/RemnantDreammm/p/15127675.html