CodeCraft-21 and Codeforces Round #711 (Div. 2)
CodeCraft-21 and Codeforces Round #711 (Div. 2)
A - GCD Sum
int main() {
IOS;
for (cin >> _; _; --_) {
ll n; cin >> n;
while (1) {
ll c = n, g = 0;
while (c) g += c % 10, c /= 10;
if (__gcd(n, g) > 1) break; ++n;
}
cout << n << '\n';
}
return 0;
}
B - Box Fitting
B 就考二分, 我是没想到
贪心想, 肯定是先放长的物品, 且尽量不浪费每一层的空间
长度都是二进制, 那就拆位放呗
再套一个二分需要多少层
int a[30];
map<int, int> lg;
bool check(int mid) {
for (ll i = 29, j = 0; ~i; j -= a[i--]) {
j = (m >> i & 1) * mid + j * 2;
if (j < a[i]) return 0;
}
return 1;
}
int main() {
IOS; rep (i, 0, 29) lg[1 << i] = i;
for (cin >> _; _; --_) {
cin >> n >> m; memset(a, 0, sizeof a);
rep (i, 1, n) cin >> k, ++a[lg[k]];
int l = 1, r = n;
while (l < r) {
int mid = l + r >> 1;
if (check(mid)) r = mid;
else l = mid + 1;
}
cout << l << '\n';
}
return 0;
}
C - Planar Reflections
来回前缀和就行了, 比如(min(n, m) > 1)最开始
我们直接预处理, 让每个隔板之间有一个 \((m - 1)\) 的粒子且这些粒子都向右
则当前倒序和为 \(a[1] = m - 1, a[2] = m - 2, ... a[m - 1] = 1\)
则最终会在第一个隔板的左边有 a[1] 个 \(m - 1\) 粒子
再隔板\(i + 1\) 和\(i\) 之间有 \(a[i]\) 个 \(m - 2\) 粒子, 且向左, 又变成了前缀和
模拟就行了
ll c[N], ans;
int main() {
IOS;
for (cin >> _; _; --_) {
cin >> n >> m;
if (m == 1) { cout << "1\n"; continue; }
if (n == 1) { cout << "2\n"; continue; }
rep (i, 2, n + 1) c[i] = 0; ans = 2;
per (i, n, 2) c[i] = c[i + 1] + 1;
rep (i, 2, m) {
ans = (ans + (i & 1 ? c[n] : c[2])) % mod;
if (i & 1) per (j, n, 2) c[j] = (c[j] + c[j + 1]) % mod;
else rep (j, 2, n) c[j] = (c[j] + c[j - 1]) % mod;
}
cout << (ans + mod) % mod << '\n';
}
return 0;
}
D - Bananas in a Microwave
分组背包, 而且还只讨论可行性, 怎么写都行
int main() {
IOS; cin >> n >> m; memset(v, -1, sizeof v); v[0] = 0;
rep (i, 1, n) {
ll x, y; cin >> _ >> x >> y;
rep (j, 0, m) if (~v[j] && v[j] ^ i) {
ll c = j;
rep (k, 1, y) {
c = _ == 1 ? ceil((c * 1e5 + x) / 1e5) : ceil(c * x / 1e5);
if (c <= m && !(~v[c])) v[c] = i;
else break;
}
}
}
rep(i, 1, m) cout << v[i] << ' ';
return 0;
}
E - Two Houses
贪心的从贡献大到那个贡献小问就行, 怎么问呢?
当然是问入度大的点\(x\) 连不连接 入度小的点\(y\)
假设连接\(x\)的点集为\(S_x\), 连接\(y\)的点集为\(S_y\)
已知 \(SIZE(S_y) \leqslant SIZE(S_x)\) 则必定存在一个点 \(z\)
\(z\)属于\(S_x\)而不属于\(S_y\), 即\(z\)连向\(x\), \(y\)连向\(z\), 如果询问得到\(x\)连向\(y\), 环就已将出来了
int a[N];
PII b[N * N];
int main() {
IOS; cin >> n; rep (i, 1, n) cin >> a[i];
rep (i, 1, n) rep (j, i + 1, n) b[++m] = a[i] < a[j] ? PII{ j, i } : PII{ i, j };
sort(b + 1, b + 1 + m, [&](PII &x, PII &y) { return a[x.fi] - a[x.se] > a[y.fi] - a[y.se]; });
rep (i, 1, m) {
cout << "? " << b[i].fi << ' ' << b[i].se << endl;
string s; cin >> s;
if (s[0] == 'Y') return cout << "! " << b[i].fi << ' ' << b[i].se, 0;
}
return cout << "! 0 0", 0;
}