Codeforces Round #565 (Div. 3)
http://codeforces.com/contest/1176
A | B | C | D | E | F |
---|---|---|---|---|---|
1A | 1A | 1A | after the game by tutorial | after the game by myself | after the game by myself |
\(rank:1097\) (赛中有点事,精神恍惚去了233)
A
由题可知,分别消掉\(1\)个\(2,3,5\)分别需要\(1,2,3\)的花费,于是我们算出\(n\)中包含的\(2,3,5\)的个数就好
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1e5 + 5;
typedef long long ll;
int q;
ll m;
int main() {
cin >> q;
while (q--) {
cin >> m;
int a = 0, b = 0, c = 0;
while (m % 2 == 0) {
a++; m /= 2;
}
while (m % 3 == 0) {
b++; m /= 3;
}
while (m % 5 == 0) {
c++; m /= 5;
}
if (m == 1)cout << a + b * 2 + c * 3 << '\n';
else cout << "-1\n";
}
return 0;
}
B
将\(a_i\)对\(3\)取模,记\(cnt[x]=x\)的数量,则\(ans\)=\(cnt[0] + min(cnt[1],cnt[2]) + \lfloor \frac{max(cnt[1],cnt[2])-min(cnt[1],cnt[2])}{3}\rfloor\)
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1e5 + 5;
typedef long long ll;
int t, n, a, cnt[3];
int main() {
cin >> t;
while (t--) {
cin >> n;
for (int i = 0; i < 3; i++)cnt[i] = 0;
for (int i = 1; i <= n; i++) {
cin >> a;
cnt[a % 3]++;
}
if (cnt[1] > cnt[2])swap(cnt[1], cnt[2]); cnt[2] -= cnt[1];
int ans = cnt[0] + cnt[1] + cnt[2] / 3;
cout << ans << '\n';
}
return 0;
}
C
记原序列中 \(subsequences\) \(4,8,15,16,23,42\)的数量为\(m\),则答案为$$n-6*m$$
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1e5 + 5;
typedef long long ll;
int n, a;
int mp[100], cnt[7];
int main() {
mp[4] = 1; mp[8] = 2; mp[15] = 3; mp[16] = 4; mp[23] = 5; mp[42] = 6;
cin >> n;
cnt[0] = 5e5 + 5;
for (int i = 1; i <= n; i++) {
cin >> a;
a = mp[a];
if (cnt[a - 1]) {
cnt[a - 1]--; cnt[a]++;
}
}
cout << n - cnt[6] * 6 << '\n';
return 0;
}
D
一个很明显的想法即是从大到小贪心,因为当前最大的一个一定要和前面的某个进行配对。
记当前数为\(x\),\(mp[x]\)= \(\{k:The\ k^{th}\ prime\ is\ x\}\),\(low[x] = x\)的最小素因子
如果\(x\)为素数,则把\(mp[x]\)加入答案。
否则,把\(x\)加入答案。
具体实现用一个\(multiset\)每次从最大的,然后删除当前以及匹配的那个。\(mp\)和\(low\)都可以通过线筛\(O(n)\)搞定
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 2750131 + 5, BOUND = 2750131;
typedef long long ll;
int n, x, primes[MAXN], cnt, low[MAXN], mp[MAXN];
bool is_prime[MAXN];
vector<int> ans;
multiset<int> st;
void init() {
is_prime[1] = 1;
for (int i = 2; i <= BOUND; i++) {
if (!is_prime[i])primes[++cnt] = i;
for (int j = 1; j <= cnt && primes[j] * i <= BOUND; j++) {
is_prime[i*primes[j]] = 1; low[i*primes[j]] = primes[j];
if (i%primes[j] == 0) {
break;
}
}
}
for (int i = 1; i <= cnt; i++) {
mp[primes[i]] = i;
}
}
int main() {
init();
cin >> n;
for (int i = 1; i <= n * 2; i++) {
cin >> x;
st.insert(x);
}
while (st.size()) {
int x = *st.rbegin();
st.erase(--st.end());
if (is_prime[x]) {
auto it = st.find(x / low[x]);
ans.push_back(x); st.erase(it);
}
else {
int t = mp[x];
auto it = st.find(t);
ans.push_back(t); st.erase(it);
}
}
for (int i = 0; i < ans.size(); i++) {
cout << ans[i] << " \n"[i == ans.size() - 1];
}
return 0;
}
E
最多选\(\lfloor \frac{n}{2} \rfloor\)个,所以我们直接遍历一遍图,对图进行黑白染色,然后输出颜色比较少的点就好,可以证明这样一定点数少于等于\(\lfloor \frac{n}{2} \rfloor\),并且满足题设条件
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 2e5 + 5;
typedef long long ll;
int t, n, m, u, v;
bool vis[MAXN];
vector<int > ans, G[MAXN];
void dfs(int u, int f, int d) {
vis[u] = 1;
if (d == 1)ans.push_back(u);
for (int v : G[u]) {
if (vis[v])continue;
dfs(v, u, d ^ 1);
}
}
int main() {
cin >> t;
while (t--) {
cin >> n >> m;
for (int i = 1; i <= n; i++)G[i].clear();
ans.clear();
for (int i = 1; i <= m; i++) {
cin >> u >> v;
G[u].push_back(v); G[v].push_back(u);
}
for (int i = 1; i <= n; i++)vis[i] = 0;
dfs(1, 0, 0);
if (ans.size() <= n / 2) {
cout << ans.size() << '\n';
for (int i = 0; i < ans.size(); i++) {
cout << ans[i] << " \n"[i == ans.size() - 1];
}
}
else {
for (int i = 1; i <= n; i++)vis[i] = 0;
ans.clear();
dfs(1, 0, 1);
cout << ans.size() << '\n';
for (int i = 0; i < ans.size(); i++) {
cout << ans[i] << " \n"[i == ans.size() - 1];
}
}
}
return 0;
}
F
简单\(dp\)。定义\(dp[i][x]\),\(i\)为当前的\(turn\),\(x\)为当前选了多少张牌,由题,我们只关心 \(x\bmod10\)的值,以此来判断什么是否\(double\ damage\),然后转移就好。细节处理看代码。
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 2e5 + 5, BOUND = 2750131;
typedef long long ll;
const ll INFL = 0x3f3f3f3f3f3f3f3f;
int n, x, c, d, mx[4], v[MAXN][6];
ll dp[MAXN][12];
priority_queue<int, vector<int>, greater<int>> s;
inline int calc(int j, int k) {
return j - k < 0;
}
int main() {
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> x;
memset(mx, 0, sizeof(mx));
for (int j = 1; j <= x; j++) {
cin >> c >> d;
if (c == 1) {
s.push(d);
if (s.size() > 3)s.pop();
}
else {
mx[c] = max(mx[c], d);
}
}
int y = 3 - s.size() + 1;
while (s.size()) {
v[i][y++] = s.top(); s.pop();
}
v[i][4] = mx[2]; v[i][5] = mx[3];
}
for (int i = 0; i < 10; i++)dp[0][i] = -INFL;
dp[0][0] = 0;
for (int i = 1; i <= n; i++) {
for (int j = 0; j < 10; j++) {
dp[i][j] = dp[i - 1][j];
if (v[i][5])dp[i][j] = max(dp[i][j], dp[i - 1][(j - 1 + 10) % 10] + v[i][5] * calc(j, 1) + v[i][5]);
if (v[i][4])dp[i][j] = max(dp[i][j], dp[i - 1][(j - 1 + 10) % 10] + v[i][4] * calc(j, 1) + v[i][4]);
if (v[i][3])dp[i][j] = max(dp[i][j], dp[i - 1][(j - 1 + 10) % 10] + v[i][3] * calc(j, 1) + v[i][3]);
if (v[i][4] && v[i][3])dp[i][j] = max(dp[i][j], dp[i - 1][(j - 2 + 10) % 10] + v[i][4] + v[i][3] + max(v[i][4], v[i][3])*calc(j, 2));
if (v[i][3] && v[i][2])dp[i][j] = max(dp[i][j], dp[i - 1][(j - 2 + 10) % 10] + v[i][2] + v[i][3] + max(v[i][2], v[i][3])*calc(j, 2));
if (v[i][3] && v[i][2] && v[i][1])dp[i][j] = max(dp[i][j], dp[i - 1][(j - 3 + 10) % 10] + v[i][3] + v[i][2] + v[i][1] + max(v[i][1], max(v[i][2], v[i][3]))*calc(j, 3));
}
}
ll ans = 0;
for (int i = 0; i < 10; i++)ans = max(ans, dp[n][i]);
cout << ans << '\n';
return 0;
}