CSP-J 2025 题解
最水CSP-J,AK了,写题解来记录一下。
number
首先把所有数字数量记一下,因为贪心,肯定要大数字放前面,类似998887777...111000。做完了。
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
int cnt[20];
string s;
signed main() {
std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
cin >> s;
int n = s.length();
s = " " + s;
for (int i = 1; i <= n; i++) {
if ('0' <= s[i] && s[i] <= '9') cnt[s[i] - '0']++;
}
for (int i = 9; i >= 0; i--) {
for (int j = 1; j <= cnt[i]; j++) {
cout << i;
}
}
return 0;
}
seat
按题意模拟即可。注意输入和输出行列顺序不一样。
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
int n, m, R;
struct node {
int s, xb;
} a[100005];
bool cmp(node x, node y) {
return x.s > y.s;
}
struct edge {
int x, y;
} ans[100005];
int tot;
signed main() {
std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
cin >> n >> m;
for (int i = 1; i <= n * m; i++) {
cin >> a[i].s;
a[i].xb = i;
}
sort(a + 1, a + n * m + 1, cmp);
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
if (i & 1) ans[++tot] = {i, j};
else ans[++tot] = {i, n - j + 1};
}
}
for (int i = 1; i <= n * m; i++) {
if (a[i].xb == 1) {
R = i;
break;
}
}
cout << ans[R].x << ' ' << ans[R].y << endl;
return 0;
}
xor
看到区间异或,先处理前缀异或数组 \(q\),这样就能 \(O(1)\) 求区间异或值了。
假设上一个区间为 \([l,r]\),贪心的,为了让区间尽可能多,新的区间 \([l',r']\) 需要满足 \(l'>r\),\(r'\) 最小。所以扫一遍前缀异或数组,当扫到 \(i\) 时,判断是否存在 \(l' \in (r,i]\) 使得 \(q_i \oplus q_{l'-1}=k\),如果存在则累加答案,并更新最新区间的右端点。可以用一个 \(\operatorname{set}\) 来存 \(q_{r+1},q_{r+2},...,q_{i}\),用来快速判断。详见代码。
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
int n, k, a[500005], q[500005], ans;
set <int> s;
signed main() {
std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
cin >> n >> k;
for (int i = 1; i <= n; i++) {
cin >> a[i];
q[i] = q[i - 1] ^ a[i];
}
s.insert(0);
for (int i = 1; i <= n; i++) {
if (s.count(q[i] ^ k)) {
ans++;
s.clear();
}
s.insert(q[i]);
}
cout << ans << endl;
return 0;
}
polygon
简单01背包,从小到大排序并依次扫每个木棍,假设扫到 \(i\),则此时只考虑选用 \([1,i]\) 中的木棍。最大的木棍就是扫到的木棍。转移时对于每个木棍可以先计算取的情况,累加答案后再计算不取的情况。注意到木棍最大值不超过 \(5000\),所以 dp 数组第二维开到 \(10004\) 就足够了。大于等于 \(10004\) 的全放到 \(10004\) 里存。
少于三根的情况可以发现是不满足题目中其他条件的,不用考虑。
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
const int p = 998244353;
const int Max = 10004;
int n, a[5005], f[5005][10005], ans;
signed main() {
std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
cin >> n;
for (int i = 1; i <= n; i++) cin >> a[i];
sort(a + 1, a + n + 1);
f[0][0] = 1;
for (int i = 1; i <= n; i++) {
for (int j = 0; j <= Max; j++) {
f[i][min(j + a[i], Max)] = (f[i][min(j + a[i], Max)] + f[i - 1][j]) % p;
}
for (int j = 2 * a[i] + 1; j <= Max; j++) ans = (ans + f[i][j]) % p;
for (int j = 0; j <= Max; j++) f[i][j] = (f[i][j] + f[i - 1][j]) % p;
}
cout << ans << endl;
return 0;
}

浙公网安备 33010602011771号