蓝桥杯每日真题之直线
Posted MangataTS
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了蓝桥杯每日真题之直线相关的知识,希望对你有一定的参考价值。
题目来源
2021年蓝桥杯省赛
题目链接:http://acm.mangata.ltd/p/P1485
考点
数学、暴力
视频讲解
https://www.bilibili.com/video/BV1BY411J795
思路
因为选取的点都是整数坐标的,于是我们最多选取
21
×
20
=
420
21\\times 20 = 420
21×20=420 个点,那么对于其中每两个点我们都能选来作为一条直线,但是这样的话可能会存在重复选择一条线,于是我们需要去重处理,那么怎么去重呢?我们知道对于一个直线的标准方程为:
A
x
+
B
y
+
C
=
0
Ax+By+C = 0
Ax+By+C=0 那么也就是说我们只要确定了
A
、
B
、
C
A、B、C
A、B、C 即可,不过这里需要注意这里的
A
、
B
、
C
A、B、C
A、B、C 是需要最简化的,否则就不能达到我们去重的效果,对于三个元素或者多个元素的结构去重,我们可以选择自己写一个结构体,但是我们也可以直接使用 vector
,然后把每个vector
扔进 set
里面即可,那么我们怎么求得
A
、
B
、
C
A、B、C
A、B、C 呢?,大家都知道两点确定直线的方程:
(
y
−
y
1
)
y
1
−
y
2
=
x
−
x
1
x
1
−
x
2
\\frac(y - y_1)y_1-y_2 = \\fracx-x_1x_1-x_2
y1−y2(y−y1)=x1−x2x−x1 那么我们稍微等式变换一下就能得到:
(
y
2
−
y
1
)
x
+
(
x
1
−
x
2
)
y
+
(
x
2
y
1
−
x
1
y
2
)
=
0
(y_2 - y_1)x + (x_1-x_2)y + (x_2y_1-x_1y_2) = 0
(y2−y1)x+(x1−x2)y+(x2y1−x1y2)=0
我们和上面一一对应就能得到:
A
=
y
2
−
y
1
、
B
=
x
1
−
x
2
、
C
=
x
2
y
1
−
x
1
y
2
A=y_2 - y_1、B=x_1-x_2、C=x_2y_1-x_1y_2
A=y2−y1、B=x1−x2、C=x2y1−x1y2,那么我们在将三者的公因数都除掉后放入vector
中,再丢入set
就完成了一条线的计算,最后我们只需要输出set
容器里面的大小即可
代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mod 1000000007
#define endl "\\n"
#define PII pair<int,int>
#define INF 0x3f3f3f3f
const double eps = 0.0000001;
int main()
vector<PII> Point;
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
int n = 20,m = 21;
// cin>>n>>m;
for(int x = 0;x < n; ++x)
for(int y = 0;y < m; ++y)
Point.push_back(x,y);
int l = Point.size();
set<vector<int>> ans;
for(int i = 0;i < l; ++i)
for(int j = i + 1;j < l; ++j)
vector<int> t;
int x1 = Point[i].first,y1 = Point[i].second;
int x2 = Point[j].first,y2 = Point[j].second;
int a,b,c;
a = y2 - y1;
b = x1 - x2;
c = x2 * y1 - x1 * y2;
int d = __gcd(__gcd(a,b),c);
t.push_back(a/d);
t.push_back(b/d);
t.push_back(c/d);
ans.insert(t);
cout<<ans.size()<<endl;
return 0;
/*
ans = 40257
*/
以上是关于蓝桥杯每日真题之直线的主要内容,如果未能解决你的问题,请参考以下文章
蓝桥杯省赛真题13python因素个数 青少年组蓝桥杯python编程省赛真题解析