AtCoder Regular Contest 116 (A~F补题记录)
补题链接:Here
第一次打 ARC,被数学题虐惨了
赛后部分数学证明学习自 ACwisher
A - Odd vs Even
【方案一】
设n有cnt个质因子2,
假设n有x个奇数因子,那么就会有m*(2^(cnt)-1)种偶数因子,即用cnt个2的子集和奇数因子配对.
因此:
当cnt=0时,没有偶数因子,此时奇数因子多.
当cnt=1时,偶数因子和奇数因子一样多.
当cnt>=2时,偶数因子比奇数因子多.
using ll = long long;
void solve() {
ll cnt = 0, n; cin >> n;
while (n % 2 == 0) n /= 2, cnt++;
if (cnt == 0)cout << "Odd\n";
else if (cnt == 1)cout << "Same\n";
else if (cnt >= 2)cout << "Even\n";
}
【方案二】
赛后打了一下表,
发现设
-
时,偶数因子有
和 ,奇数因子有 和若
且 不是 和 ,则 一定为奇数,且同时会贡献 这一偶数因子 -
时,偶数因子个数至少是奇数因子的两倍
-
是偶数因子个数为 0 个,奇数因子至少 2 个
using ll = long long;
void solve() {
ll n; cin >> n;
if (n % 4 == 0)cout << "Even\n";
else if (n % 2 == 0)cout << "Same\n";
else cout << "Odd\n";
}
B - Products of Min-Max
给出一个包含
求
先将序列按升序排序,
- 时间复杂度:
using ll = long long;
const int N = 2e5 + 10, mod = 998244353;
ll a[N], n;
void solve() {
cin >> n;
for (int i = 1; i <= n; ++i)cin >> a[i];
sort(a + 1, a + 1 + n);
ll ans = 0;
for (int i = n, tmp = 0; i >= 1; --i) {
ans = (ans + a[i] * a[i] % mod) % mod;
ans = (ans + a[i] * tmp % mod) % mod;
tmp = (2ll * tmp + a[i]) % mod;
}
cout << ans << "\n";
}
C - Multiple Sequences
给定
是 的倍数
注意到如果每次都有改变,顶多有
先计算dp方案数。
枚举有
注意第一个肯定是第一个,无需考虑
using ll = long long;
const int N = 2e5 + 10, mod = 998244353, K = 25;
int n, m, f[K][N], fac[N], ifac[N];
ll qpow(int x, int y ) {
ll ans = 1;
for (; y; y >>= 1, x = 1ll * x * x % mod)
if (y & 1) ans = ans * x % mod;
return ans;
}
int C(int x, int y) {
return 1ll * fac[x] * ifac[y] % mod * ifac[x - y] % mod;
}
void solve() {
cin >> n >> m;
for (int i = 1; i <= m; i++) f[1][i] = 1;
for (int i = 2; i <= 19; i++)
for (int j = 1; j <= m; j++)
for (int k = 2; 1ll * j * k <= m; k++)
f[i][j * k] = (f[i][j * k] + f[i - 1][j]) % mod;
fac[0] = ifac[0] = 1;
for (int i = 1; i <= n; ++i)fac[i] = 1ll * fac[i - 1] * i % mod;
ifac[n] = qpow(fac[n], mod - 2);
for (int i = n - 1; i >= 1; i--) ifac[i] = 1ll * ifac[i + 1] * (i + 1) % mod;
// -------------------上方为初始化--------------------- //
int ans = 0;
for (int i = 1; i <= min(19, n); ++i) {
int cnt = 0;
for (int j = 1; j <= m; ++j)cnt = (cnt + f[i][j]) % mod;
ans = (ans + 1ll * cnt * C(n - 1, i - 1) % mod) % mod;
}
cout << ans << '\n';
}
D - I Wanna Win The Game
给出
D题开始,没有做出来,参考了高 Rank 的解法
显然每一位都有偶数个数选择。
表示 个数和为 的方案数
是将之前和为
的 个数左移一位,并选 个数最后一位为
using ll = long long;
const int N = 5e3 + 10, mod = 998244353;
ll fac[N], ifac[N], f[N];
int n, m;
ll qpow(int x, int y ) {
ll ans = 1;
for (; y; y >>= 1, x = 1ll * x * x % mod)
if (y & 1) ans = ans * x % mod;
return ans % mod;
}
ll C(int x, int y) {
return 1ll * fac[x] * ifac[y] % mod * ifac[x - y] % mod;
}
void solve() {
cin >> n >> m;
fac[0] = ifac[0] = 1;
for (int i = 1; i <= n; ++i)fac[i] = 1ll * fac[i - 1] * i % mod;
ifac[n] = qpow(fac[n], mod - 2);
for (int i = n - 1; i >= 1; i--)ifac[i] = 1ll * ifac[i + 1] * (i + 1) % mod;
// ----------------------------------- //
f[0] = 1;
for (int i = 1; i <= m; ++i) {
if (i & 1)continue;
for (int j = 0; j <= m and i - 2 * j >= 0; ++j)
f[i] = (f[i] + 1ll * C(n, 2 * j) * f[(i - 2 * j) / 2] % mod ) % mod;
}
cout << f[m];
}
E - Spread of Information
有
二分最快时间(距离)
如果通过根节点中转能帮上
其他情况,如果
using ll = long long;
const int N = 2e5 + 10, inf = 0x3f3f3f3f;
vector<int>e[N];
int n, k, mid, ret;
int f[N], g[N];
void dfs(int u, int fa) {
g[u] = 0, f[u] = inf;
for (int v : e[u]) {
if (v == fa)continue;
dfs(v, u);
f[u] = min(f[u], f[v] + 1);
g[u] = max(g[u], g[v] + 1);
}
if (f[u] + g[u] <= mid) g[u] = -inf;
else if (g[u] == mid) f[u] = 0, g[u] = -inf, ret++;
}
bool check() {
ret = 0;
dfs(1, 0);
if (g[1] >= 0)ret++;
return ret <= k;
}
void solve() {
cin >> n >> k;
for (int i = 1, u, v; i < n; ++i) {
cin >> u >> v;
e[u].push_back(v);
e[v].push_back(u);
}
int l = 0, r = n, ans = n;
while (l <= r) {
mid = (r + l) >> 1;
if (check())r = mid - 1, ans = mid;
else l = mid + 1;
}
cout << ans;
}
F - Deque Game
const int N = 2e5 + 10;
int n, q[N];
vector<int> a[N];
int main() {
scanf("%d", &n);
int cnt = 0;
for (int i = 1; i <= n; i++) {
int k; scanf("%d", &k);
for (int j = 0, x; j < k; j++)
scanf("%d", &x), a[i].push_back(x);
cnt += (k & 1 ^ 1);
}
ll sum = 0; int len = 0;
for (int i = 1; i <= n; i++) {
if (a[i].size() & 1 ^ 1) {
if (a[i].size() == 2) {
sum += min(a[i][0], a[i][1]);
q[++len] = - (max(a[i][0], a[i][1]) - min(a[i][0], a[i][1]));
} else {
int mid0 = a[i].size() / 2 - 1, mid1 = a[i].size() / 2 + 1 - 1, ret0, ret1;
if (cnt & 1 ^ 1) {
ret0 = min(a[i][mid0], max(a[i][mid0 - 1], a[i][mid0 + 1]));
ret1 = min(a[i][mid1], max(a[i][mid1 - 1], a[i][mid1 + 1]));
} else {
ret0 = max(a[i][mid0], min(a[i][mid0 - 1], a[i][mid0 + 1]));
ret1 = max(a[i][mid1], min(a[i][mid1 - 1], a[i][mid1 + 1]));
}
sum += min(ret0, ret1);
q[++len] = - (max(ret0, ret1) - min(ret0, ret1));
}
}
}
for (int i = 1; i <= n; i++) {
if (a[i].size() & 1) {
if (a[i].size() == 1) {
sum += a[i][0];
} else {
int mid0 = (a[i].size() + 1) / 2 - 1;
if (cnt & 1 ^ 1)
sum += min(a[i][mid0], max(a[i][mid0 - 1], a[i][mid0 + 1]));
else
sum += max(a[i][mid0], min(a[i][mid0 - 1], a[i][mid0 + 1]));
}
}
}
sort(q + 1, q + len + 1);
for (int i = 1; i <= len; i += 2) sum -= q[i];
printf("%lld\n", sum);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· 分享4款.NET开源、免费、实用的商城系统
· Obsidian + DeepSeek:免费 AI 助力你的知识管理,让你的笔记飞起来!
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 全程不用写代码,我用AI程序员写了一个飞机大战