首先将每个字符串中把每个字母去重(多次出现只保留最先出现的那个字母),若两个字符串一致,我们则认为两个字符串相似。游游会提出多此询问,请你帮助她判断两个字符串是否相似。输入描述每个测试文件均包含多组测试数。第一行输入一个整数 T(1 <= T <=1000),代表数据组数,每组测试数据描述如下:对于每一组测试数据:2 行,每行一个字符串。分别代表81和82,输入保证仅有小写字母组成且长度不超过 1 0 5 10^5 105。数据保证单个测试文件的所有字符串长度之和不超过 1 0 5 10^5 105输出描述对于每一组数据,若两个字符串相似,输出"YES",否则输出"NO"。
思路:用哈希集合记录首次出现的字符,构造去重后的字符串,比对两个处理后的字符串是否一致
#include
using namespace std;
string dedup(const string& s) {
unordered_set<char> seen;
string res;
for (char c : s) {
if (!seen.count(c)) {
seen.insert(c);
res += c;
}
}
return res;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int T;
cin >> T;
while (T--) {
string s1, s2;
cin >> s1 >> s2;
cout << (dedup(s1) == dedup(s2) ? "YES\n" : "NO\n");
}
return 0;
}
游游现在有一个公司,这个公司里有n个任务,每一个任务都有一个能力值和收益值,现在有m个工人,每一个工人都有一个能力值,对于每一个任务来说,只有这个人的能力值不低于该任务需要的能力值,才可以完成这个任务。假设多个工人可以完成,同一个任务,收益为这个任务的收益值乘以这个任务完成的次数,现在想知道每一个工人最多只能安排一个任务的前提下,最大的收益值是多少?输入描述每一个文件输入第一行输入一个整数T(1<=T<=100),代表有T组测试数据。接下来T组,每一组第一行输入两个整数n,m(1≤n,m≤ 1 0 4 10^4 104)第二行输入n个整数,其中ai代表第i个任务所需要的的能力值第三行输入n个整数,其中p[i](1 ≤ p[i]≤ 1 0 5 10^5 105)代表第i个任务的收益第四行输入m个整数,其中b[i](1 ≤ b[i]≤ 1 0 5 10^5 105)代表第i个工人的能力数据保证同一个文件内n的总和不超过 1 0 5 10^5 105,m的总和不超过 1 0 5 10^5 105数据保证同一个文件内n的总和不超过 1 0 5 10^5 105,m的总和不超过 1 0 5 10^5 105输出描述对于每一组测试数据,输出一个答案代表最大的收益。
思路:任务按能力排序,工人按能力排序,双指针+最大堆维护可用任务
#include
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int T;
cin >> T;
while (T--) {
int n, m;
cin >> n >> m;
vector<pair<int, int>> tasks(n);
for (int i = 0; i < n; ++i) cin >> tasks[i].first;
for (int i = 0; i < n; ++i) cin >> tasks[i].second;
sort(tasks.begin(), tasks.end());
vector<int> workers(m);
for (int i = 0; i < m; ++i) cin >> workers[i];
sort(workers.begin(), workers.end());
priority_queue<int> pq;
long long total = 0;
int j = 0;
for (int w : workers) {
while (j < n && tasks[j].first <= w) {
pq.push(tasks[j].second);
j++;
}
if (!pq.empty()) {
total += pq.top();
pq.pop();
}
}
cout << total << '\n';
}
return 0;
}
游游给定了两个正整数n,m,他希望能将n分解为恰好m个连续(排好序后满足后一项等于前一项加一)非负整数,使得这些数的和是n,他想知道能否办到,请你帮帮他吧。连续的非负整数:即,如果将这些整数从小到大排好序后存入b数组,则第一项大于等于0,且对于任意i(1 1 0 4 10^4 104)代表数据组数,每组测试数据描还如下:在单独的一行输入两个空格分割的正整数n,m(1≤n≤ 1 0 1 8 10^18 1018;1≤m≦ 1 0 9 10^9 109),表示游游给定的正整数.输出描述对于每组测试数据:如果可以将 π 分解为m个满足题意的非负整数,则在单独的一行输出"YES",否则输出"NO"。
思路:等差数列求和公式变形,根据m的奇偶性判断整除条件
#include
using namespace std;
using ll = long long;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int T;
cin >> T;
while (T--) {
ll n, m;
cin >> n >> m;
if (2 * n % m != 0) {
cout << "NO\n";
continue;
}
ll q = 2 * n / m;
bool valid = false;
if (m % 2) { // m奇数
valid = (q % 2 == 0) && (q > m);
} else { // m偶数
valid = (q % 2 == 1) && (q > m);
}
cout << (valid ? "YES\n" : "NO\n");
}
return 0;
}
二维平面上有两个三角形△ABC 和 △DEF。求解最小半径的圆,使得完全覆盖这两个三角形。输入描述第一行输入六个整数xA,yA,xB,yB,xC,yC(-100≤xA,yA,xB,yB,xC,yC≤100)代表△ABC的三个顶点。保证三角形存在。第二行输入六个整数xD,yD,xE,yE,xF,yF(一100≤xD,yD,xE,yE,xF,yF≤100)代表△DEF的三个顶点。保证三角形存在。输出描述在一行上输出一个实数代表最小圆的半径。由于实数的计算存在误差,当误差的显级不超过 1 0 − 6 10^-6 10−6 时,您的答案都将被接受。具体来说,设您的答案为a,标准答案为b,当且仅当时,您的答案将被接受。
思路:枚举所有候选圆(两点直径圆、三点外接圆),取最小满足条件的半径
#include
using namespace std;
struct Point { double x, y; };
const double EPS = 1e-8;
// 计算两点距离平方
double dist2(const Point& a, const Point& b) {
return (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y);
}
// 三点外接圆
pair<Point, double> circumCircle(const Point& A, const Point& B, const Point& C) {
double a1 = 2*(B.x - A.x), b1 = 2*(B.y - A.y);
double c1 = B.x*B.x + B.y*B.y - A.x*A.x - A.y*A.y;
double a2 = 2*(C.x - A.x), b2 = 2*(C.y - A.y);
double c2 = C.x*C.x + C.y*C.y - A.x*A.x - A.y*A.y;
double det = a1*b2 - a2*b1;
if (fabs(det) < EPS) return {{0,0}, -1};
Point center = {
(b2*c1 - b1*c2)/det,
(a1*c2 - a2*c1)/det
};
return {center, sqrt(dist2(center, A))};
}
bool checkCover(const Point& center, double r2, const vector<Point>& pts) {
for (auto& p : pts) {
double dx = p.x - center.x;
double dy = p.y - center.y;
if (dx*dx + dy*dy > r2 + EPS) return false;
}
return true;
}
double solve(const vector<Point>& points) {
double min_r = 1e18;
const int n = points.size();
for (int i = 0; i < n; ++i) {
for (int j = i+1; j < n; ++j) {
Point center = {
(points[i].x + points[j].x)/2,
(points[i].y + points[j].y)/2
};
double r2 = dist2(points[i], center);
if (checkCover(center, r2, points)) {
min_r = min(min_r, sqrt(r2));
}
}
}
// 枚举三点组合
for (int i = 0; i < n; ++i) {
for (int j = i+1; j < n; ++j) {
for (int k = j+1; k < n; ++k) {
auto [center, r] = circumCircle(points[i], points[j], points[k]);
if (r < 0) continue;
if (checkCover(center, r*r, points)) {
min_r = min(min_r, r);
}
}
}
}
return min_r;
}
int main() {
vector<Point> points(6);
for (int i = 0; i < 6; ++i) {
if (i < 3) cin >> points[i].x >> points[i].y;
else cin >> points[i+3].x >> points[i+3].y;
}
cout << fixed << setprecision(12) << solve(points) << endl;
return 0;
}