VP*12;
rating:800--1100--1300--2000
A. Regular Bracket Sequences
给出n,构造长度为2*n的匹配括号序列。
思路: 构造的方式有很多种,但是我们要考虑较为简单地一种。我们可以使初始序列为左侧是n个(,右侧是n个),每一次将中间的一对()放到整个括号外侧。
AC Code:
#include <bits/stdc++.h>
#pragma GCC optimize(2)
template <typename T>
inline void read(T &x) {
x = 0;
int f = 1;
char ch = getchar();
while (!isdigit(ch)) {
if (ch == '-')
f = -1;
ch = getchar();
}
while (isdigit(ch)) {
x = x * 10 + ch - '0', ch = getchar();
}
x *= f;
}
template <typename T>
void write(T x) {
if (x < 0)
putchar('-'), x = -x;
if (x > 9)
write(x / 10);
putchar(x % 10 + '0');
}
#define INF 0x3f3f3f3f
typedef long long ll;
const double PI = acos(-1);
const double eps = 1e-6;
const int mod = 1e9 + 7;
const int N = 1e6 + 5;
std::string s1 = "()";
std::string s2 = "((";
std::string s3 = "))";
std::string s4 = ")(";
int t, n;
int main() {
// freopen("test.in","r",stdin);
// freopen("output.in", "w", stdout);
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
std::cin >> t;
while (t--) {
std::cin >> n;
if (n == 1) {
std::cout << "()" << '\n';
} else if (n == 2) {
std::cout << "()()" << '\n';
std::cout << "(())" << '\n';
} else {
for (int i = n; i >= 1; i--) {
for (int j = 1; j <= i; j++) {
std::cout << "(";
}
for (int j = 1; j <= i; j++) {
std::cout << ")";
}
for (int j = 1; j <= n - i; j++) {
std::cout << "()";
}
std::cout << '\n';
}
}
}
return 0;
}
B. Combinatorics Homework
给出a个A,b个B,c个C,问是否可以通过一定次序的排列使得相邻两个字母相同的对数是m。
思路:与昨天做的一个题比较类似。很容易想到是要找到用这些字母可以排列组合得到相邻字母相同对数的范围,最大值是(a-1)+(b-1)+(c-1),最小值是不同的字母交叉放置,此时最少的对数是c-(a+b)-1,其中c是数量最多的字母个数,只要m在这个范围内即可,否则无法得到。
AC Code:
#include <bits/stdc++.h>
#pragma GCC optimize(2)
template <typename T>
inline void read(T &x) {
x = 0;
int f = 1;
char ch = getchar();
while (!isdigit(ch)) {
if (ch == '-')
f = -1;
ch = getchar();
}
while (isdigit(ch)) {
x = x * 10 + ch - '0', ch = getchar();
}
x *= f;
}
template <typename T>
void write(T x) {
if (x < 0)
putchar('-'), x = -x;
if (x > 9)
write(x / 10);
putchar(x % 10 + '0');
}
#define INF 0x3f3f3f3f
typedef long long ll;
const double PI = acos(-1);
const double eps = 1e-6;
const int mod = 1e9 + 7;
const int N = 1e6 + 5;
std::string s1 = "()";
std::string s2 = "((";
std::string s3 = "))";
std::string s4 = ")(";
int t, a[4], m;
int main() {
// freopen("test.in","r",stdin);
// freopen("output.in", "w", stdout);
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
std::cin >> t;
while (t--) {
std::cin >> a[1] >> a[2] >> a[3] >> m;
std::sort(a+1,a+4);
if (m > (a[1]+a[2]+a[3]) - 3)
std::cout << "NO" << '\n';
else if(m<std::max(0,a[3]-(a[1]+a[2])-1))
std::cout << "NO" << '\n';
else std::cout<<"YES"<<'\n';
}
return 0;
}
C. Slay the Dragon
给出若干勇士和很多恶龙,每次只能一个勇士去打龙,只能是勇士的力量大于龙的防御才可以;剩下的勇士守卫城堡,只能在剩下的勇士的力量之和大于等于龙的攻击力时才可以,每次花费一金币可以增加勇士一点力量,问最少需要多少金币才可能打败龙并且保卫城堡。
思路:每次查找与龙的防御最靠近的勇士去攻击龙,剩下的人保卫城堡,若符合条件的勇士有两个,那么就取两种情况的最小值。
AC Code:
#include <bits/stdc++.h>
#pragma GCC optimize(2)
template <typename T>
inline void read(T &x) {
x = 0;
int f = 1;
char ch = getchar();
while (!isdigit(ch)) {
if (ch == '-')
f = -1;
ch = getchar();
}
while (isdigit(ch)) {
x = x * 10 + ch - '0', ch = getchar();
}
x *= f;
}
template <typename T>
void write(T x) {
if (x < 0)
putchar('-'), x = -x;
if (x > 9)
write(x / 10);
putchar(x % 10 + '0');
}
#define INF 0x3f3f3f3f
typedef long long ll;
const double PI = acos(-1);
const double eps = 1e-6;
const int mod = 1e9 + 7;
const int N = 2e5 + 5;
int n, m;
ll a[N];
int main() {
// freopen("test.in","r",stdin);
// freopen("output.in", "w", stdout);
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
std::cin >> n;
ll sum = 0;
for (int i = 1; i <= n; i++) {
std::cin >> a[i];
sum += a[i];
}
std::sort(a + 1, a + 1 + n);
std::cin >> m;
while (m--) {
ll x, y;
std::cin >> x >> y;
ll ans = 0;
int pos = std::lower_bound(a + 1, a + 1 + n, x) - a;
if (a[pos] > x && pos != 1) {
ll ans1 = std::max(y - (sum - a[pos]), (ll)0);
ll ans2 = std::max(y - (sum - a[pos - 1]), (ll)0) + x - a[pos - 1];
std::cout << std::min(ans1, ans2) << '\n';
} else if (pos == n + 1)
std::cout << std::max((ll)0, y - (sum - a[pos - 1])) + x - a[pos - 1] << '\n';
else
std::cout << std::max(y - (sum - a[pos]), (ll)0) << '\n';
}
return 0;
}
D. The Strongest Build
给出n个格子,每个格子可以选择一件装备,每个格子有相应的多种选择,但是有若干组选择被ban了,也就是不能选择这样的一组选择,问怎样选择使得装备的累计和最大。
思路:首先选择的肯定是每个卡槽的最后一个位置,但是如果这个结果被ban了,就不能使用了。
然后枚举这m个不可选的结果,每个结果的对应每一个位置减去一生成新的序列,如果它没有被禁且算出来的值的和大于当前的最大值,就进行更新答案。
AC Code:
#include <bits/stdc++.h>
#pragma GCC optimize(2)
template <typename T>
inline void read(T &x) {
x = 0;
int f = 1;
char ch = getchar();
while (!isdigit(ch)) {
if (ch == '-')
f = -1;
ch = getchar();
}
while (isdigit(ch)) {
x = x * 10 + ch - '0', ch = getchar();
}
x *= f;
}
template <typename T>
void write(T x) {
if (x < 0)
putchar('-'), x = -x;
if (x > 9)
write(x / 10);
putchar(x % 10 + '0');
}
#define INF 0x3f3f3f3f
typedef long long ll;
const double PI = acos(-1);
const double eps = 1e-6;
const int mod = 1e9 + 7;
const int N = 2e5 + 5;
int n, m, c, x;
ll maxn;
int main() {
// freopen("test.in","r",stdin);
// freopen("output.in", "w", stdout);
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
std::map<std::vector<int>, int>vis;
std::vector<int>vec[11], ban[N], res, a;
std::cin >> n;
for (int i = 1; i <= n; i++) {
std::cin >> c;
for (int j = 1; j <= c; j++) {
std::cin >> x;
vec[i].push_back(x);
}
}
std::cin >> m;
for (int i = 1; i <= m; i++) {
a.clear();
for (int j = 1; j <= n; j++) {
std::cin >> x;
ban[i].push_back(x);
}
vis[ban[i]] = 1;
}
a.clear();
for (int i = 1; i <= n; i++) {
a.push_back(vec[i].size());
}
if (!vis[a]) { //若最大的一组没被ban自然选这一组
for (auto i : a)
std::cout << i << ' ';
} else {
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
a.clear();
a = ban[i]; //枚举所有被ban的情况
a[j - 1] = std::max(a[j - 1] - 1, 1);
if (!vis[a]) {
ll sum = 0;
for (int xx = 0; xx < a.size(); xx++) {
sum += vec[xx + 1][a[xx] - 1];
}
if (sum > maxn) {
res = a;
maxn = sum;
}
}
}
}
for (auto i : res) {
std::cout << i << ' ';
}
std::cout << '\n';
}
return 0;
}
若有错误请指教,谢谢!
orzorz