教练要求做的题,难度可能有些简单。
Codeforces 22D. Segments
考虑每个线段按照右节点排序后,贪心选取即可。
时间复杂度 (mathcal O(nlog n))
#include <bits/stdc++.h>
using namespace std;
const int N = 1005;
int n;
struct line {
int l, r;
} seg[N];
bool vis[N];
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%d %d", &seg[i].l, &seg[i].r);
if (seg[i].l > seg[i].r) swap(seg[i].l, seg[i].r);
}
sort(seg + 1, seg + 1 + n, [](line lhs, line rhs) {
if (lhs.r == rhs.r) return lhs.l < rhs.l;
return lhs.r < rhs.r;
});
vector<int> ans;
for (int i = 1; i <= n; i++) {
if (!vis[i]) {
ans.emplace_back(seg[i].r);
int j = i + 1;
while (seg[j].l <= seg[i].r) {
vis[j] = 1;
j++;
}
}
}
printf("%d
", ans.size());
for (auto i : ans) printf("%d ", i);
return 0;
}
Codeforces 9D. How many trees?
令 (f[i][j]) 表示前 (i) 个数,深度为 (j) 的方案数。
考虑枚举左右节点的深度,即
[f[i+1][j]=sum_k f[i][L] imes f[i-k][R]
]
/*
* Author: chhokmah
* Date: 2020-08-22 09:48:35
*/
#include <bits/stdc++.h>
using namespace std;
const int N = 40;
int n, k;
long long f[N][N];
int main() {
scanf("%d %d", &n, &k);
f[1][1] = f[0][0] = 1;
for (int i = 1; i < n; i++) {
for (int j = 0; j <= i; j++) {
for (int left = 0; left <= i; left++) {
for (int right = 0; right <= i - j; right++) {
f[i + 1][max(left, right) + 1] += f[j][left] * f[i - j][right];
}
}
}
}
long long ans = 0;
for (int i = k; i <= n; i++) ans += f[n][i];
printf("%I64d
", ans);
return 0;
}
Codeforces 7D. Palindrome Degree
考虑一个 (mathcal O(nlog n)) 的暴力。
考虑优化这个暴力,我们记录前缀的答案,然后可以把 (O(log n)) 的缩小优化为 (O(1))。
时间复杂度 (mathcal O(n))
/*
* Author: chhokmah
* Date: 2020-08-22 10:40:34
*/
#include <bits/stdc++.h>
using namespace std;
constexpr int N = 5e6 + 5;
template <int base, int mod>
struct hash_st {
constexpr static int Base = base, P = mod;
int64_t hashp[N], hashs[N], ord[N];
string s;
int n;
void prep() {
ord[0] = 1;
for (int i = 1; i <= n; i++) ord[i] = ord[i - 1] * Base % P;
hashp[0] = s[0];
for (int i = 1; i < n; i++) hashp[i] = (hashp[i - 1] * Base + s[i]) % P;
hashs[n - 1] = s[n - 1];
for (int i = n - 2; i >= 0; i--)
hashs[i] = (hashs[i + 1] * Base + s[i]) % P;
}
hash_st() {}
hash_st(string st) { s = st, n = s.length(), prep(); }
void init(string st) { s = st, n = s.length(), prep(); }
int64_t getp(int l, int r) {
return l == 0 ? hashp[r]
: (hashp[r] - hashp[l - 1] * ord[r - l + 1] % P + P) % P;
}
int64_t gets(int l, int r) {
return r == n - 1 ? hashs[l]
: (hashs[l] - hashs[r + 1] * ord[r - l + 1] % P + P) % P;
}
};
string s;
hash_st<129, 998244353> hash1;
int dp[N];
bool chk(int l, int r) { return hash1.getp(l, r) == hash1.gets(l, r); }
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> s;
bool flag = 0;
int n = s.length(), ans = 0;
for (int i = 1; i < n; i++)
if (s[0] != s[i]) flag = 1;
if (!flag) {
for (int i = 1; i <= n; i++) ans += log2(i) + 1;
cout << ans << '
';
return 0;
}
hash1.init(s);
for (int i = 0; i < n; i++) {
int cnt = 0, len = i + 1;
if (chk(0, i)) {
dp[i]++;
len >>= 1;
if (chk(i - len + 1, i) && len >= 1) dp[i] += dp[len - 1];
ans += dp[i];
}
}
cout << ans << '
';
return 0;
}
Codeforces 8E. Beads
比较好的一道题,我们先考虑概括其约束:
- 原串 $leq $ 逆串 (iff) 前缀 $leq $ 后缀
- 原串 $leq $ 反串 (iff) 第 (1) 位为 (0)
- 原串 $leq $ 逆反串 (iff) 前缀 $leq $ 后缀的逆串
我们考虑一位一位确定答案,我们需要计算当前这一位为 (0) 的方案数,并不断和 (k) 靠近。
时间复杂度 (mathcal O(50n^2))
需要注意奇数的情况的细节处理。
/*
* Author: chhokmah
* Date: 2020-08-22 14:07:51
*/
#include <bits/stdc++.h>
using namespace std;
int n;
long long k;
long long dp[55][2][2];
int a[55];
long long numberDigitDp(int r, int flag1, int flag2) {
if (r < n - r + 1) return 1;
if (dp[r][flag1][flag2] != -1) return dp[r][flag1][flag2];
long long& ans = dp[r][flag1][flag2];
ans = 0;
if (r == n - r + 1) {
for (int i = 0; i <= 1; i++)
if (a[r] == i || a[r] == -1)
if ((!flag2 || (flag2 && i <= (i ^ 1))))
ans += numberDigitDp(r - 1, flag1 & 1, flag2 & 0);
} else {
for (int i = 0; i <= 1; i++)
if (a[n - r + 1] == i || a[n - r + 1] == -1)
for (int j = 0; j <= 1; j++)
if (a[r] == j || a[r] == -1)
if ((!flag1 || (flag1 && i <= j)) &&
(!flag2 || (flag2 && i <= (j ^ 1))))
ans += numberDigitDp(r - 1, flag1 & (i == j), flag2 & (i != j));
}
return ans;
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
cin >> n >> k;
memset(a, -1, sizeof a);
memset(dp, -1, sizeof dp);
a[1] = 0;
if (numberDigitDp(n, 1, 1) <= k) {
printf("-1
");
return 0;
}
printf("0");
for (int i = 2; i <= n; i++) {
memset(dp, -1, sizeof dp);
a[i] = 0;
long long pro = numberDigitDp(n, 1, 1);
if (pro <= k) {
printf("1");
k -= pro;
a[i] = 1;
} else
printf("0");
}
return 0;
}