补题记录
A. Remainder
#include <bits/stdc++.h>
using namespace std;
int n, m, k;
char s[200005];
int main()
{
scanf("%d%d%d", &n, &m, &k);
scanf("%s", s);
int ans = 0;
for (int i = 0; i < m; i++)
{
if (i == k)
{
if (s[n - 1 - i] == '0')
ans++;
}
else
{
if (s[n - 1 - i] == '1')
ans++;
}
}
printf("%d", ans);
}
B. Polycarp Training
#include <bits/stdc++.h>
using namespace std;
int a[200005];
int main()
{
int n;
scanf("%d", &n);
for (int i = 0; i < n; i++)
scanf("%d", &a[i]);
sort(a, a + n);
int j = 0, ans = 0;
for (int i = 1; i <= n; i++)
{
while (a[j] < i && j < n)
j++;
if (j == n)
break;
ans++;
j++;
}
printf("%d", ans);
}
C. Good String
暴力
#include <bits/stdc++.h>
using namespace std;
char s[200005];
vector<char>ans;
int main()
{
int n;
scanf("%d", &n);
scanf("%s", s);
for (int i = 0; i < n - 1;)
{
if (s[i] == s[i + 1])
i++;
else
{
ans.push_back(s[i]);
ans.push_back(s[i + 1]);
i += 2;
}
}
printf("%d\n", n - ans.size());
for (int i = 0; i < ans.size(); i++)
printf("%c", ans[i]);
}
D. Almost All Divisors
如果存在答案,那么那个数一定是序列中最小的数和最大的数的乘积
#include <bits/stdc++.h>
#define ll long long
using namespace std;
int a[305];
vector<int>v;
void calc(ll k)
{
for (ll i = 2; i <= sqrt(k); i++)
{
if (k % i == 0)
{
v.push_back(i);
if (i * i != k)
v.push_back(k / i);
}
}
sort(v.begin(), v.end());
}
int main()
{
int T;
scanf("%d", &T);
while (T--)
{
v.clear();
int n;
scanf("%d", &n);
for (int i = 0; i < n; i++)
scanf("%d", &a[i]);
sort(a, a + n);
ll ans = 1LL * a[0] * a[n - 1];
calc(ans);
if (v.size() != n)
printf("-1\n");
else
{
for (int i = 0; i < n; i++)
{
if (a[i] != v[i])
{
printf("-1\n");
goto qwe;
}
}
printf("%lld\n", ans);
}
qwe:;
}
}
E. Two Arrays and Sum of Functions
一个顺序,一个反序,这样相乘答案才会最小,注意要先算 a数组 的贡献,再排序相乘。
#include <bits/stdc++.h>
#define ll long long
using namespace std;
int n;
ll a[200005], b[200005];
const ll mod = 998244353;
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; i++)scanf("%lld", &a[i]);
for (int i = 1; i <= n; i++)scanf("%lld", &b[i]);
for (int i = 1; i <= n; i++)a[i] = (ll)(n - i + 1) * i * a[i];
sort(a + 1, a + n + 1, [](ll q, ll w) {
return q > w;
});
sort(b + 1, b + n + 1);
ll ans = 0;
for (int i = 1; i <= n; i++) {
ans = (ans + ((a[i] % mod) * b[i] % mod) % mod) % mod;
}
printf("%lld", ans);
}
F1. F2. Microtransactions (hard version)
二分天数,然后如果有打折,我们就在最后打折的那天买下需要的数量的物品,这样就可以做到能买到的打折的数量最多,(贪心),然后再从前往后判断,这一天是否有这么多钱,如果没有的话,就忽略掉这个打折,否则,买下这个打折的商品,然后我们统计有多少个还没有买的商品,在最后一天以每个2元的代价买下,最后如果剩下的钱非负,这个天数就合法,否则,不合法。
#include <bits/stdc++.h>
using namespace std;
int a[200005];
vector<int>v[200005];
bool vis[200005];
int buy[400005];
int cnt;
bool check(int mid)
{
memset(buy, 0, sizeof(buy));
memset(vis, false, sizeof(vis));
for (int i = min(mid, 200000); i >= 1; i--)
{
for (int j = 0; j < v[i].size(); j++)
{
if (vis[v[i][j]] == false)
{
vis[v[i][j]] = true;
buy[i] += a[v[i][j]];
}
}
}
int had = 0;
int money = 0;
for (int i = 1; i <= mid; i++)
{
money++;
if (money >= buy[i])
{
money -= buy[i];
had += buy[i];
}
else
{
had += money;
money = 0;
}
}
money -= (cnt - had) * 2;
if (money >= 0)
return true;
else
return false;
}
int main()
{
int n, m;
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++)
{
scanf("%d", &a[i]);
cnt += a[i];
}
for (int i = 0; i < m; i++)
{
int q, w;
scanf("%d%d", &q, &w);
v[q].push_back(w);
}
int l = cnt, r = cnt * 2;
while (l + 1 < r)
{
int mid = (l + r) / 2;
if (check(mid))
r = mid;
else
l = mid;
}
if (!check(l))
l = r;
printf("%d", l);
}