A题:Buy a Pen
思路:
大水题
code:
inline void solve() {
int r, g, b; cin >> r >> g >> b;
string s; cin >> s;
int ans;
if (s[0] == 'R') ans = min(g, b);
else if (s[0] == 'G') ans = min(r, b);
else ans = min(r, g);
cout << ans << endl;
return;
}
B题:Right Triangle
思路:
垂直两边内积为0
code:
inline void solve() {
vector<PII> a(3);
for (int i = 0; i < 3; i ++ ) cin >> a[i].first >> a[i].second;
function<bool(PII, PII, PII)> check = [&](PII a, PII b, PII c) {
PII ab = {b.first - a.first, b.second - a.second};
PII ac = {c.first - a.first, c.second - a.second};
if (ab.first * ac.first + ab.second * ac.second == 0) return true;
return false;
};
for (int i = 0; i < 3; i ++ ) {
if (check(a[i], a[(i + 1) % 3], a[(i + 2) % 3])) return cout << "Yes\n", void();
}
cout << "No\n";
return;
}
C题:Sum = 0
思路:
每个选取的x都有一个范围,那么其总和就有一个范围[l, r]。
显然地,对于l > 0,或者 r < 0 答案是肯定不存在的,否则就存在
那么我们可令所有xi先为最小,然后加上差值即可。
code:
inline void solve() {
int n; cin >> n;
vector<PLL> a(n + 1);
ll l = 0, r = 0;
for (int i = 1; i <= n; i ++ ) {
cin >> a[i].first >> a[i].second;
l += a[i].first, r += a[i].second;
}
if (l > 0 || r < 0) return cout << "No\n", void();
ll d = -l;
cout << "Yes\n";
for (int i = 1; i <= n; i ++ ) {
ll minv = min(d, a[i].second - a[i].first);
d -= minv, a[i].first += minv;
cout << a[i].first << " \n"[i == n];
}
return;
}
D题:Shortest Path 3
思路:
思路就是题目... shortest path
我们利用优先队列优化的dij最短路即可。
不会点这 -- > 优先队列优化最短路
code:
struct edge {
int v, w;
};
struct node {
ll dis, u;
bool operator > (const node& a) const {return dis > a.dis;}
};
inline void solve() {
int n, m; cin >> n >> m;
vector<int> a(n + 1);
for (int i = 1; i <= n; i ++ ) cin >> a[i];
vector<vector<edge>> e(n + 1);
for (int i = 1; i <= m; i ++ ) {
int u, v, c; cin >> u >> v >> c;
e[u].push_back({v, c}), e[v].push_back({u, c});
}
vector<ll> dis(n + 1);
for (int i = 1; i <= n; i ++ ) dis[i] = 1e18;
vector<bool> vis(n + 1);
priority_queue<node, vector<node>, greater<node>> q;
dis[1] = a[1];
q.push({a[1], 1});
while (q.size()) {
int u = q.top().u; q.pop();
if (vis[u]) continue;
vis[u] = 1;
for (auto ed : e[u]) {
int v = ed.v, w = ed.w;
if (dis[v] > dis[u] + w + a[v]) {
dis[v] = dis[u] + w + a[v];
q.push({dis[v], v});
}
}
}
for (int i = 2; i <= n; i ++ ) cout << dis[i] << ' ';
return;
}
E题:Count Arithmetic Subsequences
思路:
arithmetic sequences 等差子序列
我们定义dp[j][i][k] 为a[i]结尾,公差为 a[i] - a[j] 的大小为k的子序列的数量
这样我们从左到右遍历i的时候,对于一个新的a[i],我们去i的前面找一个j,这样我们就得到了一个公差,再去j的前面找一个k,那么我们就可以知道对于a[i]可以衔接在哪个以a[k]结尾的公差相同的子序列后面了。
code:
int dp[81][81][81];
inline void solve() {
mod = 998244353;
int n; cin >> n;
vector<int> a(n + 1), ans(n + 1);
for (int i = 1; i <= n; i ++ ) cin >> a[i];
for (int i = 1; i <= n; i ++ ) {
dp[0][i][1] = 1;
for (int j = 1; j < n; j ++ ) {
dp[j][i][2] = 1;
for (int k = 1; k < j; k ++ ) {
if (a[i] - a[j] == a[j] - a[k]) {
for (int l = 1; l <= j; l ++ ) {
dp[j][i][l + 1] = (dp[j][i][l + 1] + dp[k][j][l]) % mod;
}
}
}
}
}
for (int i = 1; i <= n; i ++ ) {
for (int j = 0; j < i; j ++ ) {
for (int k = 1; k <= i; k ++ ) {
ans[k] = (ans[k] + dp[j][i][k]) % mod;
}
}
}
for (int i = 1; i <= n; i ++ ) cout << ans[i] << " \n"[i == n];
return;
}