Codeforces Round #666 (Div. 2) A~E
A
#include <bits/stdc++.h>
#define all(n) (n).begin(), (n).end()
#define se second
#define fi first
#define pb push_back
#define mp make_pair
#define sqr(n) (n)*(n)
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define per(i,a,b) for(int i=(a);i>=(b);--i)
#define IO ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr)
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
typedef pair<ll, ll> PLL;
typedef vector<int> VI;
typedef double db;
const int N = 1e5 + 5;
int n, m, _, k;
int cnt[26];
char s[1005];
int main() {
IO;
for (cin >> _; _; --_) {
cin >> n;
memset(cnt, 0, sizeof cnt);
rep (i, 1, n) {
cin >> s;
for (int i = 0; s[i]; ++i) ++cnt[s[i] - 'a'];
}
bool f = 1;
rep (i, 0, 25) if (cnt[i] % n) { f = 0; break; }
if (f) cout << "YES\n";
else cout << "NO\n";
}
return 0;
}
B
首先发现这题的费用, 要么单调递增, 要么先减后增(就是三分, 不过有个确定点 c = 1)
且我们有个答案上线, 即 c = 1, $ ans_{max} = \sum_i^n (a[i] - 1)$
所以我们直接遍历 c 即可, 只要费用小于当前费用, 就一直搜, 大于当前费用就bereak, 复杂度是够得
#include <bits/stdc++.h>
#define all(n) (n).begin(), (n).end()
#define se second
#define fi first
#define pb push_back
#define mp make_pair
#define sqr(n) (n)*(n)
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define per(i,a,b) for(int i=(a);i>=(b);--i)
#define IO ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr)
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
typedef pair<ll, ll> PLL;
typedef vector<int> VI;
typedef double db;
const int N = 1e5 + 5;
int n, m, _, k;
int a[N];
int main() {
IO; cin >> n; ll ans = 0;
rep (i, 0, n - 1) cin >> a[i], ans += a[i] - 1;
sort(a, a + n);
for (int i = 2; ; ++i) {
ll res = 0, cur = 1;
rep (j, 0, n - 1) {
res += abs(a[j] - cur);
if (res >= ans) break;
cur *= i;
}
if (res >= ans) break;
ans = res;
}
cout << ans << '\n';
return 0;
}
C
6行, 代表三次就能算出答案
对 2 n, len = n - 1, 将 期间的数变成 n 的倍数
对 1 1, 将 a[1] 变成 len 的倍数
左后 1 n, 都是 n 的倍数 直接 -a[i], 即可
ps 要是n == 1, 更好想
#include <bits/stdc++.h>
#define all(n) (n).begin(), (n).end()
#define se second
#define fi first
#define pb push_back
#define mp make_pair
#define sqr(n) (n)*(n)
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define per(i,a,b) for(int i=(a);i>=(b);--i)
#define IO ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr)
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
typedef pair<ll, ll> PLL;
typedef vector<int> VI;
typedef double db;
const int N = 1e5 + 5;
int n, m, _, k;
ll a[N];
int main() {
IO; cin >> n >> a[1];
cout << "1 1\n" << n - (a[1] % n) << '\n';
a[1] += n - (a[1] % n);
if (n > 1) cout << "2 " << n << '\n';
rep (i, 2, n) {
cin >> a[i]; ll res = a[i] % n * (n - 1);
cout << res << ' ';
a[i] += res;
}
if (n > 1) cout << '\n';
cout << "1 " << n << '\n';
rep (i, 1, n) cout << -a[i] << ' ';
if (n == 1) cout << "\n1 1\n0";
return 0;
}
D
存在一堆石子的数量大于其他堆的和, 那么先手占住 必胜
否则终将转化为 每堆 都是 1, 直接判奇偶性
#include <bits/stdc++.h>
#define all(n) (n).begin(), (n).end()
#define se second
#define fi first
#define pb push_back
#define mp make_pair
#define sqr(n) (n)*(n)
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define per(i,a,b) for(int i=(a);i>=(b);--i)
#define IO ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr)
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
typedef pair<ll, ll> PLL;
typedef vector<int> VI;
typedef double db;
const int N = 1e5 + 5;
int n, m, _, k;
int main() {
IO;
for (cin >> _; _; --_) {
cin >> n; int s = 0, mx = 0;
rep (i, 1, n) cin >> m, s += m, mx = max(mx, m);
if (mx > s - mx || (s & 1)) cout << "T\n";
else cout << "HL\n";
}
return 0;
}
E
每层有两种情况 直接干掉这层boss hp = 0, 攻击boss使得boss hp = 1且处于强制转换楼层状态
直接干掉boss 相当于 b = r1 * a[i] + r3, 攻击一下相当于 a = min(r1 * (m + 1), r2)
设状态 f[i][j], 表示在 i 层, boss hp = j
则 (i > 1)
f[i][1] = min(f[i - 1][0] + d(上楼) + a(i层行动), f[i - 1][1] + d(强制传送) + d(传送回来) + r3(干掉 i-1 层boss) + d(上楼) + a(i层行动))
= (化简)
f[i][0] = min(min(f[i - 1][0] + d(上楼) + b(行动), f[i - 1][1] + d(强制传送) + d(传送回来) + r3(干掉 i-1 层boss) + d(上楼) + b(行动)),
f[i - 1][0] + d(强制上楼) + a(行动) + d(强制下楼) + r3(干掉 i - 1 层boss) + d(上楼) + r3(干掉 i 层boss))
= (化简)
当 i = 1, f[1][1] = a, f[1][0] = b;
注意在最后一层中 f[i][0] 被转移的时候 f[i - 1][1] + d(强制传送) + d(传送回来) + r3(干掉 i-1 层boss) + d(上楼) + b(行动) //把b(行动)前移
可表示为 f[i - 1][1] + d(强制上楼) + b(行动) + d(传送下楼) + r3(干掉 i-1 层boss) + d(上楼), 发现最后一步上楼是多余的
#include <bits/stdc++.h>
#define all(n) (n).begin(), (n).end()
#define se second
#define fi first
#define pb push_back
#define mp make_pair
#define sqr(n) (n)*(n)
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define per(i,a,b) for(int i=(a);i>=(b);--i)
#define IO ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr)
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
typedef pair<ll, ll> PLL;
typedef vector<int> VI;
typedef double db;
const int N = 1e6 + 5;
int n, m, _, k;
ll a, b, c, c1, c2, c3, d;
ll f[N][2];
int main() {
IO; cin >> n >> c1 >> c2 >> c3 >> d >> m;
c = (d << 1) + c1;
f[1][0] = c1 * m + c3; f[1][1] = min(c2, c1 * (m + 1));
rep(i, 2, n) {
cin >> m; a = min(c2, c1 * (m + 1)); b = c1 * m + c3;
f[i][1] = min(f[i - 1][0] + a, f[i - 1][1] + c + a) + d;
f[i][0] = min(min(f[i - 1][0], f[i - 1][1] + c) + b, a + c1 + f[i - 1][1] + c) + d;
}
cout << min(min(f[n][0], f[n][1] + c), f[n - 1][1] + c + c1 * m + c3);
return 0;
}