The 14-th BIT Campus Programming Contest
A. 两只脑斧
#include <bits/stdc++.h>
using namespace std;
using i32 = int32_t;
using i64 = long long;
using vi = vector<int>;
using pii = pair<int,int>;
i32 main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
int n;
cin >> n;
string s;
for(int i = 1, x; i <= n; i ++) {
cin >> s;
x = s[0] - '0';
if(x == 7) cout << "I";
else if(x == 0) cout << "X";
else if(x & 1) cout << "E";
else cout << "I";
}
return 0;
}
C. 赛尔逵传说
贪心题目,因为攻击力只能是\(k\)的倍数,因此没使用一次水果相当于少挨一次打,因此我们可以贪心的选择对方攻击力最高的。
#include <bits/stdc++.h>
using namespace std;
using i32 = int32_t;
using i64 = long long;
#define int i64
using vi = vector<int>;
using pii = pair<int,int>;
i32 main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
int n, k, c;
cin >> n >> k >> c;
vector<pii> a(n);
for(auto &[x, d] : a) cin >> d >> x;
ranges::sort(a, greater<>());
int res = 0;
for(auto &[x, d] : a) {
int y = (d + k - 1) / k - 1;
if(y <= c) c -= y;
else y -= c, c = 0, res += y * x;
}
cout << res << "\n";
return 0;
}
E. 只有一端开口的瓶子
我们至多使用两个瓶子就一定可以排序。先要考虑的就是用一个瓶子是否可以排序,我们可以模拟一下一个瓶子的方案。
#include <bits/stdc++.h>
using namespace std;
using i32 = int32_t;
using i64 = long long;
using vi = vector<int>;
using pii = pair<int,int>;
const int mod = 2019;
void solve() {
int n;
cin >> n;
int now = 1;
stack<int> stk;
for(int i = 1, x; i <= n; i ++) {
cin >> x;
stk.push(x);
while(not stk.empty() and stk.top() == now)
stk.pop(), now ++;
}
if(now == n + 1) cout << "1\n";
else cout << "2\n";
return;
}
i32 main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
i32 T;
cin >> T;
while(T --) solve();
return 0;
}
F. 风王之瞳
一个大小为\(d\times d\)正方形里面包含了\(d\)个内接正方形。
#include <bits/stdc++.h>
using namespace std;
using i32 = int32_t;
using i64 = long long;
#define int i64
using vi = vector<int>;
using pii = pair<int,int>;
void solve() {
int n, m;
cin >> n >> m;
int d = min(n, m);
int res = 0;
for(int i = 1; i <= d;i ++)
res += i * (n - i + 1) * (m - i + 1);
cout << res << "\n";
return ;
}
i32 main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
int T;
cin >> T;
while(T --) solve();
return 0;
}
H. 目标是成为数论大师
求根公式解一下。
#include <bits/stdc++.h>
using namespace std;
using i32 = int32_t;
using i64 = long long;
using vi = vector<int>;
using pii = pair<int,int>;
void solve(){
i64 a, b;
cin >> a >> b;
if(a == 0) {
cout << 1 << "\n" << b << "\n";
return;
}
i64 A = 1, B = - (2 * b + a), C = b * b;
i64 delta = B * B - 4 * A * C;
if(delta == 0) {
i64 x = - B / (2 * A);
assert(A * x * x + B * x + C == 0);
cout << 1 << "\n" << x << "\n";
} else {
double d = sqrt(1.0 * delta);
i64 x1 = - (B + d) / (2 * A);
i64 x2 = - (B - d) / (2 * A);
assert(x1 != x2);
assert(A * x1 * x1 + B * x1 + C == 0);
assert(A * x2 * x2 + B * x2 + C == 0);
if(x1 > x2) swap(x1, x2);
if(x1 * a < 0 or x1 - b < 0) {
cout << 1 << "\n" << x2 << "\n";
}else if(x2 - b < 0 or x2 * a < 0 ) {
cout << 1 << "\n" << x1 << "\n";
}else{
cout << 2 << "\n" << x1 << " " << x2 << "\n";
}
}
return;
}
i32 main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
i32 T;
cin >> T;
while(T --) solve();
return 0;
}
J. 金色传说
记\(p[i]\)表示长度为\(i\)的数字之和,记\(f[i]\)表示长度为\(i\)且至少存在一个符号的所有等式之和。因此对于询问\(x\),答案就是\(f[x] + p[x]\)。
\(f[i]\)如何计算,我们可以考虑枚举最后一个数,然后前面的数有两种情况,没有符号和有符号。我们考虑对于最后一个数\(x\),如果存在加\(x\)就一定存在减\(x\)。因此会吧最后一个数产生的贡献全部都消掉。所以我们可以用前缀和实现快速的转移。
#include <bits/stdc++.h>
using namespace std;
using i32 = int32_t;
using i64 = long long;
#define int i64
using vi = vector<int>;
using pii = pair<int,int>;
const int mod = 998244353;
struct mint {
i64 x;
mint(int x = 0) : x(x) {}
mint &operator=(int o) {return x = o, *this;}
mint &operator+=(mint o) { return (x += o.x) >= mod && (x -= mod), * this;}
mint &operator-=(mint o) { return (x -= o.x) < 0 && (x += mod), *this;}
mint &operator*=(mint o) { return x = x * o.x % mod, *this;}
mint &operator^=(int b) {
mint w = *this;
mint ret = 1;
for(; b; b >>= 1, w *= w) if(b & 1) ret *= w;
return x = ret.x, *this;
}
friend mint operator+(mint a, mint b) { return a += b;}
friend mint operator-(mint a, mint b) { return a -= b;}
friend mint operator*(mint a, mint b) { return a *= b;}
friend mint operator^(mint a, int b) { return a ^= b;}
};
i32 main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
int N = 5e5;
vector<mint> q(N + 1);
q[0] = 1;
vector<mint> p(N + 1);
for(int i = 1; i <= N; i ++) {
q[i] = q[i - 1] * 10;
for(int j = 0; j <= 9; j ++)
p[i] += p[i - 1] * 10 + j * q[i - 1];
}
vector<mint> preF(N + 1), preP(N + 1);
vector<mint> f(N + 1), g(N + 1), pre(N + 1), ans(N + 1);
for(int i = 3; i <= N; i ++) {
preP[i] = (preP[i - 1] + p[i - 2]) * 10;
f[i] += preP[i] * 2;
if(i >= 5) {
preF[i] = (preF[i - 1] + f[i - 2]) * 10;
f[i] += preF[i] * 2;
}
}
int T;
cin >> T;
for(int x; T; T --) {
cin >> x;
if(x <= 2 ) cout << p[x].x << "\n";
else cout << (f[x] + p[x]).x << "\n";
}
return 0;
}
K. 多项式求导
直接模拟求导的过程即可。
#include <bits/stdc++.h>
using namespace std;
using i32 = int32_t;
using i64 = long long;
using vi = vector<int>;
using pii = pair<int,int>;
const int mod = 998244353;
i32 main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
i64 n, k;
cin >> n >> k;
vi res(n + 1);
for(i64 i = n, x, y; i >= 0; i --) {
cin >> y, x = i;
for(int j = 0; j < k; j ++)
y = y * x % mod, x = max(x - 1, 0ll);
if(i - k >= 0) res[i - k] = y % mod;
}
for(int i = n; i >= 0; i --)
cout << res[i] << " ";
return 0;
}
L. 旅行的意义
我们在DAG上的 dp,\(f[i]\)表示从\(i\)出发可以玩多少天。首先如果\(i\ne 1\),则需要花费\(1\)天坐火车来。第一天一定会玩,第二天有\(\frac{1}{\mathrm{e[i].size()} + 1}\)的概率会玩。
然后我们枚举所有的子节点,$f[x] \leftarrow f[x] + \frac{f[y]}{\mathrm{e[x].size()}} $。
#include <bits/stdc++.h>
using namespace std;
using i32 = int32_t;
using i64 = long long;
#define int i64
using vi = vector<int>;
using pii = pair<int, int>;
const int mod = 998244353;
int power(int x, int y) {
int ret = 1;
while (y) {
if (y & 1) ret = ret * x % mod;
x = x * x % mod;
y /= 2;
}
return ret;
}
int inv(int x) {
return power(x, mod - 2);
}
void solve() {
int n, m;
cin >> n >> m;
vector<vi> e(n + 1);
for (int x, y; m; m--) {
cin >> x >> y;
e[x].push_back(y);
}
vi f(n + 1); // f[x] 从 x 出发玩的期望天数
auto dfs = [&](auto &&self, int x) -> int {
if (f[x] != 0) return f[x];
f[x] = (1 + (x != 1) + inv(e[x].size() + 1)) % mod;
for (auto y: e[x])
f[x] = (f[x] + inv(e[x].size()) * self(self, y)) % mod;
return f[x];
};
cout << dfs(dfs, 1) << "\n";
return;
}
i32 main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
int T;
cin >> T;
while (T--)
solve();
return 0;
}