二维:小苯的星轨
题目描述
平面直角坐标系中有 nnn 颗星星,第 iii 颗星星位于整点(xi,yi)。(x_i,y_i)。(xi,yi)。
保证所有星星的位置两两不同,但允许某颗星星位于原点 (0,0)(0,0)(0,0)。
小苯会选择两颗不同的星星,组成一个无序星星对。如果经过这两颗星星的直线同时经过原点 (0,0)(0,0)(0,0),那么称这个星星对是合法的。
注意:
1、 选择第 iii 颗和第 jjj 颗星星,与选择第 jjj 颗和第 iii 颗星星是同一个星星对;
2、 如果两颗星星中有一颗位于原点,那么这个星星对一定合法;
3、 由于所有星星的位置两两不同,任意两颗星星都能确定唯一一条直线。
请计算合法无序星星对的数量。
输入描述:
第一行包含一个整数 TTT,表示测试数据的组数。 对于每组测试数据: 第一行包含一个整数 nnn,表示星星的数量。
接下来 nnn 行,每行包含两个整数 xi,yix_i,y_ixi,yi,表示第 iii 颗星星的坐标。
数据范围如下:
1≤T≤100,1\le T\le100,1≤T≤100,
1≤n≤2×105,1\le n\le2\times10^5,1≤n≤2×105,
−109≤xi,yi≤109,-10^9\le x_i,y_i\le10^9,−109≤xi,yi≤109,
(xi,yi)≠(xj,yj)(i≠j)。(x_i,y_i)\ne(x_j,y_j)\quad(i\ne j)。(xi,yi)=(xj,yj)(i=j)。
保证所有测试数据中 nnn 的总和不超过 2×1052\times10^52×105。
输出描述:
对于每组测试数据,输出一行一个整数,表示合法无序星星对的数量。
示例1
输入
2 4 0 0 1 1 2 2 1 0 3 0 0 1 2 2 1
输出
4 2
说明
第一组数据中,合法的星星对为:
-
(0,0) 与 (1,1);
-
(0,0) 与 (2,2);
-
(0,0) 与 (1,0);
-
(1,1) 与 (2,2)。
因此答案为 4。
第二组数据中,只有位于原点的星星分别与另外两颗星星组成的两个星星对合法,因此答案为 2。
#include <iostream>
#include<vector>
#include<string>
#include<algorithm>
#include<map>
#define int long long
using namespace std;
int gcd(int x, int y)
{
return y == 0 ? x : gcd(y, x % y);
}
signed main()
{
int t;
cin >> t;
while (t--)
{
int n;
cin >> n;
vector<int>x(n);
vector<int>y(n);
for (int i = 0;i < n;i++)
cin >> x[i] >> y[i];
map<pair<int, int>, int>mp;
for (int i = 0;i < n;i++)
{
if (x[i] == 0 && y[i] == 0)
{
mp[{0, 0}]++;
}
else if (x[i] == 0)
{
mp[{0, 1}]++;
}
else if (y[i] == 0)
{
mp[{1, 0}]++;
}
else
{
int g = gcd(x[i], y[i]);
int xx = x[i] / g;
int yy = y[i] / g;
if (xx < 0)
{
xx *= (-1);
yy *= (-1);
}
mp[{xx, yy}]++;
}
}
int cnt = 0;
for (auto e : mp)
{
cnt += (e.second - 1) * e.second / 2;
}
cnt += (n - mp[{0, 0}])* mp[{0, 0}];
cout << cnt << "\n";
}
return 0;
}
三维:八角玄冰草·万向刺
题目描述
八角玄冰草作为霍雨浩的第四个魂灵,赋予了强大的冰属性能力。在史莱克学院的战术训练中,他正面对一个三维立体的虚拟训练场,场内散布着若干定位靶,他需要利用八角玄冰草赋予他的魂技——八角万向刺,以尽可能少的技能释放次数,将场上的所有定位靶悉数击破。
开始前,训练场会向霍雨浩推送一张战场地图:整个立体空间被均匀地划分为一个个格点,霍雨浩自己、每个定位靶、以及空位分别落在其对应的格点上。
这张地图可以看作一个 n × m × l 的三维立体字符矩阵,其中:
H 表示霍雨浩所在的位置,有且仅有一个
T 表示定位靶的位置
. 表示空位
霍雨浩全程站定于 H 所在的格点,不会移动。在此基础上,他每次可以朝三维空间中的任意一个方向(方向取值连续,不限于坐标轴或格点方向)释放万向刺,沿该方向从 H 出发形成一条无限长的射线;万向刺能穿透路径上的一切障碍,射线上所有的 T 都会被击破。已知定位靶不会移动,且所有目标都位于格点上。
两个定位靶能被同一次攻击击破,当且仅当它们与霍雨浩的连线方向完全相同(即方向向量成正实数倍关系)。
注意:一次技能只沿一条射线射出,因此反方向(例如 (1,0,0) 与 (-1,0,0))不视为同一方向,需要分别用一次技能击破。
请你求出最少需要释放几次技能,才能击破所有定位靶。
输入描述:
第一行包含三个正整数 n, m, l,分别表示矩阵的深度、行数、列数。 接下来,按照深度优先的顺序输入 n 个二维矩阵块。每个矩阵块有 m 行,每行一个长度为 l 的字符串,仅由字符 H、T、. 组成。 输入保证整个三维矩阵中恰好只有一个 H。
输出描述:
输出一个整数,表示最少需要的技能释放次数。
示例1
输入
1 3 5 T...T .T.T. ..H..
输出
2
备注:
1 ≤ n, m, l ≤ 100 输入字符仅包含 H、T、. 保证有且仅有一个 H
#include<iostream>
#include<vector>
#include<map>
using namespace std;
#define int long long
struct node
{
int x, y, z;
bool operator<(const node& other) const
{
if (x != other.x)
return x < other.x;
if (y != other.y)
return y < other.y;
return z < other.z;
}
};
int gcd(int x, int y)
{
return y == 0 ? x : gcd(y, x % y);
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);
int n, m, l;
cin >> n >> m >> l;
int hx, hy, hz;
vector<vector<string>> g(n, vector<string>(m));
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
cin >> g[i][j];
for (int k = 0; k < l; k++)
{
if (g[i][j][k] == 'H')
hx = i, hy = j, hz = k;
}
}
}
map<node, int> mp;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
for (int k = 0; k < l; k++)
{
if (g[i][j][k] != 'T')
continue;
int x = i - hx;
int y = j - hy;
int z = k - hz;
int d = gcd(gcd(abs(x), abs(y)), abs(z));
mp[{x / d, y / d, z / d}]++;
}
}
}
cout << mp.size();
return 0;
}
328

被折叠的 条评论
为什么被折叠?



