题目出的对退役老年选手很友好,拿个T恤跑路…
下面的题解仅代表个人观点,出了问题,概不负责。
比赛链接:https://tianchi.aliyun.com/oj/15165469968503404?spm=5176.15098393.J_6210563800.8.6b8b5cd6dK6WtT
小栖必须在一个三角形中才能施展魔法,现在他知道自己的坐标和三个点的坐标,他想知道他能否施展魔法
输入: triangle = [[0,0],[2,0],[1,2]] point= [1,1]
输出: "Yes"
输入: triangle = [[0,0],[2,0],[1,1]] point= [2,1]
输出: "No"
判断是否在三角形内,模板题。
class Vector2d
{
public:
double x_;
double y_;
public:
Vector2d(double x, double y) : x_(x), y_(y) {
}
Vector2d() : x_(0), y_(0) {
}
//二维向量叉乘, 叉乘的结果其实是向量,方向垂直于两个向量组成的平面,这里我们只需要其大小和方向
double CrossProduct(const Vector2d vec)
{
return x_ * vec.y_ - y_ * vec.x_;
}
//二维向量点积
double DotProduct(const Vector2d vec)
{
return x_ * vec.x_ + y_ * vec.y_;
}
//二维向量减法
Vector2d Minus(const Vector2d vec) const
{
return Vector2d(x_ - vec.x_, y_ - vec.y_);
}
//判断点M,N是否在直线AB的同一侧
static bool IsPointAtSameSideOfLine(const Vector2d &pointM, const Vector2d &pointN,
const Vector2d &pointA, const Vector2d &pointB)
{
Vector2d AB = pointB.Minus(pointA);
Vector2d AM = pointM.Minus(pointA);
Vector2d AN = pointN.Minus(pointA);
//等于0时表示某个点在直线上
return AB.CrossProduct(AM) * AB.CrossProduct(AN) >= 0;
}
};
//三角形类
class Triangle
{
private:
Vector2d pointA_, pointB_, pointC_;
public:
Triangle(Vector2d point1, Vector2d point2, Vector2d point3)
: pointA_(point1), pointB_(point2), pointC_(point3)
{
//todo 判断三点是否共线
}
//计算三角形面积
double ComputeTriangleArea()
{
//依据两个向量的叉乘来计算,可参考http://blog.csdn.net/zxj1988/article/details/6260576
Vector2d AB = pointB_.Minus(pointA_);
Vector2d BC = pointC_.Minus(pointB_);
return fabs(AB.CrossProduct(BC) / 2.0);
}
bool IsPointInTriangle1(const Vector2d pointP)
{
double area_ABC = ComputeTriangleArea();
double area_PAB = Triangle(pointP, pointA_, pointB_).ComputeTriangleArea();
double area_PAC = Triangle(pointP, pointA_, pointC_).ComputeTriangleArea();
double area_PBC = Triangle(pointP, pointB_, pointC_).ComputeTriangleArea();
if (fabs(area_PAB + area_PBC + area_PAC - area_ABC) < 0.000001)
return true;
else
return false;
}
bool IsPointInTriangle2(const Vector2d pointP)
{
return Vector2d::IsPointAtSameSideOfLine(pointP, pointA_, pointB_, pointC_) &&
Vector2d::IsPointAtSameSideOfLine(pointP, pointB_, pointA_, pointC_) &&
Vector2d::IsPointAtSameSideOfLine(pointP, pointC_, pointA_, pointB_);
}
bool IsPointInTriangle3(const Vector2d pointP)
{
Vector2d AB = pointB_.Minus(pointA_);
Vector2d AC = pointC_.Minus(pointA_);
Vector2d AP = pointP.Minus(pointA_);
double dot_ac_ac = AC.DotProduct(AC);
double dot_ac_ab = AC.DotProduct(AB);
double dot_ac_ap = AC.DotProduct(AP);
double dot_ab_ab = AB.DotProduct(AB);
double dot_ab_ap = AB.DotProduct(AP);
double tmp = 1.0 / (dot_ac_ac * dot_ab_ab - dot_ac_ab * dot_ac_ab);
double u = (dot_ab_ab * dot_ac_ap - dot_ac_ab * dot_ab_ap) * tmp;
if (u < 0 || u > 1)
return false;
double v = (dot_ac_ac * dot_ab_ap - dot_ac_ab * dot_ac_ap) * tmp;
if (v < 0 || v > 1)
return false;
return u + v <= 1;
}
bool IsPointInTriangle4(const Vector2d pointP)
{
Vector2d PA = pointA_.Minus(pointP);
Vector2d PB = pointB_.Minus(pointP);
Vector2d PC = pointC_.Minus(pointP);
double t1 = PA.CrossProduct(PB);
double t2 = PB.CrossProduct(PC);
double t3 = PC.CrossProduct(PA);
return t1 * t2 >= 0 && t1 * t3 >= 0;
}
};
class Solution
{
public:
/**
* @param triangle: Coordinates of three points
* @param point: Xiaoqi's coordinates
* @return: Judge whether you can cast magic
*/
string castMagic(vector<vector<int>> &triangle, vector<int> &point)
{
Triangle tri(Vector2d(triangle[0][0], triangle[0][1]),
Vector2d(triangle[1][0], triangle[1][1]),
Vector2d(triangle[2][0], triangle[2][1]));
return tri.IsPointInTriangle3(Vector2d(point[0], point[1])) ? "Yes" : "No";
}
};
有一个数组num,现在定义区间对的和等于:左区间的最大值加右区间的最小值 由于小栖特别能突发奇想,他突然想知道多个区间对和的异或和是多少
输入: num = [1,2,3,4,5] ask = [[1,2,3,4],[1,2,4,5]]
输出: 3
说明: [1,2,3,4]区间异或对和为5,[1,2,4,5]区间异或对和为6,5 xor 6 = 3
求区间最值,用线段树和RMQ都能搞,我用的RMQ
typedef long long ll;
#define N 100010
ll maxx[N][20];
ll minn[N][20];
void RMQ(ll n)
{
for (ll j = 1; j < 20; j++)
for (ll i = 1; i <= n; i++)
if (i + (1 << j) - 1 <= n)
{
maxx[i][j] = max(maxx[i][j - 1], maxx[i + (1 << (j - 1))][j - 1]);
minn[i][j] = min(minn[i][j - 1], minn[i + (1 << (j - 1))][j - 1]);
}
}
ll get_max(ll a, ll b)
{
ll k = (ll)(log(b - a + 1.0) / log(2.0));
return max(maxx[a][k], maxx[b - (1 << k) + 1][k]);
}
ll get_min(ll a, ll b)
{
ll k = (ll)(log(b - a + 1.0) / log(2.0));
return min(minn[a][k], minn[b - (1 << k) + 1][k]);
}
class Solution
{
public:
/**
* @param num: array of num
* @param ask: llerval pairs
* @return: return the sum of xor
*/
int Intervalxor(vector<int> &num, vector<vector<int>> &ask)
{
for (ll i = 0; i < num.size(); i++)
{
minn[i + 1][0] = maxx[i + 1][0] = num[i];
}
ll n = num.size();
RMQ(n);
ll ans = 0;
for (vector<int> as : ask)
{
ll l1 = as[0], r1 = as[1];
ll l2 = as[2], r2 = as[3];
ll tmp = get_max(l1, r1) + get_min(l2, r2);
ans ^= tmp;
}
return ans;
}
};
小栖最近很喜欢回文串,由于小栖的幸运数字是5,他想知道形似“abcba"的回文串在他给定的字符串中的数量
样例 1:
输入:s = "abcba"
输出:1
样例 2:
输入:s = "abcbabcccb"
输出:2
解释:形似”abcba“的字符串有”abcba“和”cbabc“
直接O(n)遍历判断,不用算法。
class Solution
{
public:
/**
* @param s: The given string
* @return: return the number of Five-character palindrome
*/
int pd(string &s, int mid)
{
bool f1 = s[mid - 1] == s[mid + 1];
bool f2 = s[mid - 2] == s[mid + 2];
bool f3 = (s[mid - 1] != s[mid - 2]) & (s[mid] != s[mid - 2]) & (s[mid] != s[mid - 1]);
return f1 & f2 & f3;
}
int Fivecharacterpalindrome(string &s)
{
int n = s.size();
if (n < 5)
return 0;
int ans = 0;
for (int i = 2; i < n - 2;)
{
if (pd(s, i))
{
i += 2;
ans++;
}
else
{
i++;
}
}
return ans;
}
};
小栖有一个金字塔,每一层都有编号.
小栖可以在不同点间移动,假设小栖现在在(x1,y1),他能够移动到的下一个点(x2,y2)满足x2>=x1&&y2>=y1x2>=x1&&y2>=y1 现在小栖呆在(k,k)处,由于我们不能确定小栖现在在哪儿,所以你需要求出所有点(k,k)到达(n,n)的方案数的和。
输入:n=3,k=[1,2,3]
输出:9
超级卡特兰数/大施罗德数 裸题。
题目中求的是 k 到 n 的方案数,所以对于每一个三角形而言,要求第 n-k+1
个大施罗德数。
模板可以看这里:https://blog.csdn.net/PleasantlY1/article/details/84074637
typedef long long LL;
const LL mod = 1e9 + 7;
const LL maxn = 1e7 + 10;
LL num[maxn];
LL inverse(LL x, LL y) ///快速幂加费马小定理求逆元
{
LL sum = 1;
while (y)
{
if (y & 1)
sum = sum * x % mod;
y /= 2;
x = x * x % mod;
}
return sum % mod;
}
class Solution
{
public:
/**
* @param n: The number of pyramid levels n
* @param k: Possible coordinates k
* @return: Find the sum of the number of plans
*/
int pyramid(int n, vector<int> &k)
{
num[1] = num[0] = 1;
for (int i = 2; i <= n; i++)
{
num[i] = ((6 * i - 3) * num[i - 1] % mod - (i - 2) * num[i - 2] % mod + mod) % mod * inverse(i + 1, mod - 2) % mod;
}
LL ans = 0;
for (auto x : k)
{
x = n - x + 1;
LL tmp = x == 1 ? 1 : num[x - 1] * 2 % mod;
ans = (ans + tmp) % mod;
}
return int(ans);
}
};