A. Drinks Choosing
分析:优先将成对的处理掉,然后只剩下一堆单个的,除以2向上取整,加起来就是答案。
#include "bits/stdc++.h"
using namespace std;
const int mod = 1e9 + 7;
int a[1004];
unordered_map<int, int> mp;
int main() {
int n, k;
cin >> n >> k;
for (int i = 0; i < n; ++i) {
scanf("%d", &a[i]);
mp[a[i]]++;
}
int cnt = 0;
int ans = 0;
for (auto it : mp) {
ans += it.second / 2;
cnt += it.second % 2;
}
ans *= 2;
ans += (cnt + 1) / 2;
cout << ans << endl;
}
B. Sport Mafia
分析:设放糖果放了m轮,那么吃了n-m个糖果
有
化简得
可以在的时间复杂度内求出。
#include "bits/stdc++.h"
using namespace std;
const int mod = 1e9 + 7;
int a[1004];
int main() {
long long n, k;
cin >> n >> k;
long long x = (n + k) * 2;
long long ans = 0;
for (long long i = 1; i * i <= x; ++i) {
if (i * (i + 3) == x) {
ans = n - i;
break;
}
}
cout << ans << endl;
}
C. Basketball Exercise
分析:dp[i][j]表示前i个,最后一个选的是j组的最大值,线性跑一遍就可以了。
#include "bits/stdc++.h"
using namespace std;
const int mod = 1e9 + 7;
long long a[100004];
long long b[100004];
long long dp[100004][2];
int main() {
int n;
cin >> n;
for (int i = 1; i <= n; ++i) {
scanf("%lld", &a[i]);
}
for (int i = 1; i <= n; ++i) {
scanf("%lld", &b[i]);
}
dp[1][0] = a[1];
dp[1][1] = b[1];
for (int i = 2; i <= n; ++i) {
dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] + a[i]);
dp[i][1] = max(dp[i - 1][1], dp[i - 1][0] + b[i]);
}
cout << max(dp[n][0], dp[n][1]) << endl;
}
D1. Submarine in the Rybinsk Sea (easy edition)
分析:由于位数都是相同的,那么每个数的贡献等于每位依次乘10的奇数次方和偶数次方的和再乘上n。
#include "bits/stdc++.h"
using namespace std;
const int mod = 998244353;
long long a[100004];
int main() {
long long n;
cin >> n;
long long ans = 0LL;
for (int i = 1; i <= n; ++i) {
scanf("%lld", &a[i]);
long long temp = a[i];
long long base = 1LL;
while (temp) {
ans += base * (temp % 10) % mod;
ans %= mod;
base *= 100LL;
base %= mod;
temp /= 10;
}
temp = a[i];
base = 10;
while (temp) {
ans += base * (temp % 10) % mod;
ans %= mod;
base *= 100LL;
base %= mod;
temp /= 10;
}
}
cout << ans * n % mod << endl;
}
D2. Submarine in the Rybinsk Sea (hard edition)
分析:按照位数分组,最多只有10位,枚举100次就可以了。注意位数不一样的时候,每位的权值也会有所变化。
#include "bits/stdc++.h"
using namespace std;
const int mod = 998244353;
int get_di(long long x) {
long long ans = 0;
while (x) {
ans++;
x /= 10;
}
return ans;
}
long long a[100004][14];
int cnt[14];
int main() {
long long n;
cin >> n;
long long x;
memset(cnt, 0, sizeof(cnt));
for (int i = 1; i <= n; ++i) {
scanf("%lld", &x);
int d = get_di(x);
a[cnt[d]++][d] = x;
}
long long ans = 0;
for (int i = 1; i <= 10; ++i) {
for (int j = 1; j <= 10; ++j) {
for (int k = 0; k < cnt[i]; ++k) {
long long base = 1;
long long temp = a[k][i];
long long y = j;
long long sum = 0;
while (temp) {
sum += base * (temp % 10) % mod;
sum %= mod;
if (y > 0)base *= 100;
else base *= 10;
base %= mod;
temp /= 10;
y--;
}
base = 10;
temp = a[k][i];
y = j - 1;
while (temp) {
sum += base * (temp % 10) % mod;
sum %= mod;
if (y > 0)base *= 100;
else base *= 10;
base %= mod;
temp /= 10;
y--;
}
sum *= cnt[j];
sum %= mod;
ans += sum;
ans %= mod;
}
}
}
cout << ans << endl;
}
E. OpenStreetMap
分析:小数据二维rmq或树套树可做,但这道不行。这个题的特殊点在于每次询问的矩阵大小是固定的。
那么我们首先对于每行,处理出该点(i,j)到(i,j - b+1)中的最小值。
然后再对于每列,由上述求出的数组,找出点(i,j)到(i - a + 1,j)的最小值,就是答案。
用单列队列很容易维护。
#include "bits/stdc++.h"
using namespace std;
const int mod = 998244353;
long long a[4004][4004];
long long g[4004 * 3004];
int main() {
int n, m, A, B, x, y, z;
cin >> n >> m >> A >> B >> g[0] >> x >> y >> z;
for (int i = 1; i <= n * m; ++i) {
g[i] = (g[i - 1] * x + y) % z;
}
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
int id = (i - 1) * m + j - 1;
a[i][j] = (g[id]);
}
}
long long ans = 0;
for (int i = 1; i <= n; ++i) {
deque<pair<int,int>>q;
q.clear();
for (int j = 1; j <= m; ++j) {
while(q.size() && q.back().first >= a[i][j])q.pop_back();
while(q.size() && q.front().second + B - 1 < j)q.pop_front();
q.push_back({a[i][j],j});
a[i][j]=q.front().first;
}
}
for (int j = 1; j <= m; ++j) {
deque<pair<int,int>>q;q.clear();
for (int i = 1; i <= n; ++i) {
while(q.size() && q.back().first >= a[i][j])q.pop_back();
while(q.size() && q.front().second + A - 1 < i)q.pop_front();
q.push_back({a[i][j],i});
if(i>=A&&j>=B)ans += q.front().first;
}
}
cout<<ans<<endl;
}