T1:两数归零

ai+aj=0aj=ai,用 std::map<int, int> 来统计即可

代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
using ll = long long;
int main() {
int n;
cin >> n;
vector<int> a(n);
rep(i, n) cin >> a[i];
ll ans = 0;
map<int, int> mp;
for (int x : a) {
ans += mp[-x];
mp[x]++;
}
cout << ans << '\n';
return 0;
}

T2:牛奶供应(四)

x=p+(mdi)

显然每次应该优先购买 x 最小的那一次,这样就能保证 x 小的尽可能多买,x 大的尽可能少买
可以用 std::multiset 来维护

代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
using ll = long long;
using P = pair<int, int>;
int main() {
int n, m, L;
cin >> n >> m >> L;
multiset<P> s;
rep(i, n) {
int d, w, p;
cin >> d >> w >> p;
p += m-d;
s.emplace(p, w);
}
ll ans = 0;
while (L) {
auto [p, w] = *s.begin();
if (L <= w) {
ans += (ll)L*p;
break;
}
else {
ans += (ll)w*p;
s.erase(s.begin());
L -= w;
}
}
cout << ans << '\n';
return 0;
}

T3:工作安排

简单贪心

对于第 i 份任务和第 j 份任务,第 i 份任务先于第 j 份任务之前完成  tifi+(ti+tj)×fj<tjfj+(ti+tj)×fitifj<tjfi

按这个规则做一遍排序即可

注意开 long long

代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
using ll = long long;
struct node {
int t, f;
node() {}
node(int t, int f): t(t), f(t) {}
bool operator<(node& o) const {
return (ll)t*o.f < (ll)o.t*f;
}
};
int main() {
int n;
cin >> n;
vector<node> ps(n);
rep(i, n) cin >> ps[i].t >> ps[i].f;
sort(ps.begin(), ps.end());
ll ans = 0, now = 0;
for (auto [t, f] : ps) {
now += t;
ans += now*f;
}
cout << ans << '\n';
return 0;
}

T4:单词解密

dp[i] 表示将 s 的前 i 个字符转化为明文的方案数

转移方程:

如果 1si9,则可以直接转化为 ai
dp[i+1] += dp[i]

如果 10si1si¯<=26,则可以将这两个字符转成 jz
dp[i+1] += dp[i-1]

初始化:dp[0]=1

代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
using ll = long long;
//const int mod = 998244353;
const int mod = 1000000007;
struct mint {
ll x;
mint(ll x=0):x((x%mod+mod)%mod) {}
mint operator-() const {
return mint(-x);
}
mint& operator+=(const mint a) {
if ((x += a.x) >= mod) x -= mod;
return *this;
}
mint& operator-=(const mint a) {
if ((x += mod-a.x) >= mod) x -= mod;
return *this;
}
mint& operator*=(const mint a) {
(x *= a.x) %= mod;
return *this;
}
mint operator+(const mint a) const {
return mint(*this) += a;
}
mint operator-(const mint a) const {
return mint(*this) -= a;
}
mint operator*(const mint a) const {
return mint(*this) *= a;
}
mint pow(ll t) const {
if (!t) return 1;
mint a = pow(t>>1);
a *= a;
if (t&1) a *= *this;
return a;
}
// for prime mod
mint inv() const {
return pow(mod-2);
}
mint& operator/=(const mint a) {
return *this *= a.inv();
}
mint operator/(const mint a) const {
return mint(*this) /= a;
}
};
istream& operator>>(istream& is, mint& a) {
return is >> a.x;
}
ostream& operator<<(ostream& os, const mint& a) {
return os << a.x;
}
int main() {
string s;
cin >> s;
int n = s.size();
vector<mint> dp(n+1);
dp[0] = 1;
rep(i, n) {
if (s[i] != '0') dp[i+1] += dp[i];
if (i >= 1) {
string t = s.substr(i-1, 2);
if ("10" <= t and t <= "26") dp[i+1] += dp[i-1];
}
}
cout << dp[n] << '\n';
return 0;
}