T1:两数归零
\(a_i + a_j = 0 \Leftrightarrow a_j = -a_i\),用 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+(m-d_i)\)
显然每次应该优先购买 \(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\) 份任务之前完成 \(\Leftrightarrow ~ t_if_i + (t_i+t_j) \times f_j < t_jf_j + (t_i+t_j) \times f_i \Leftrightarrow t_if_j < t_jf_i\)
按这个规则做一遍排序即可
注意开 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\) 个字符转化为明文的方案数
转移方程:
如果 \(1 \leqslant s_i \leqslant 9\),则可以直接转化为 \(a \sim i\)
\(\Rightarrow\) dp[i+1] += dp[i]
如果 \(10 \leqslant \overline{s_{i-1}s_i} <= 26\),则可以将这两个字符转成 \(j \sim z\)
\(\Rightarrow\) 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;
}