补题链接:Here

第一次打 ARC,被数学题虐惨了

赛后部分数学证明学习自 ACwisher

A - Odd vs Even

\(T(1≤T≤2×10^5)\)组测试数据,每次询问一个正整数 \(N(1≤N≤2×10^{18})\) 的奇数因子多还是偶数因子多。


【方案一】

设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";
}

【方案二】

赛后打了一下表,

发现设 \(N = 4k + r\)

  • \(r = 2\) 时,\(N = 4k + 2 = 2(2k +1)\)

    偶数因子有 \(2\) 和 \(2(2k + 1)\) ,奇数因子有 \(1\) 和 \(2k + 1\)

    若 \(d|(2k + 1)\) 且 \(d\) 不是 \(1\) 和 \(2k + 1\),则 \(d\) 一定为奇数,且同时会贡献 \(2d\) 这一偶数因子

  • \(r = 0\) 时,\(N = 4k\)

    偶数因子个数至少是奇数因子的两倍

  • \(r = 1\ or\ 3\) 是

    偶数因子个数为 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

给出一个包含 \(n\) 个数的序列 \(A\),有 \(2^{n−1}\)个 \(A\) 的非空子序列 \(B\)

求 \(\sum max(B)\times min(B)\)


先将序列按升序排序,

\[\begin{split}
ans &= \sum_{i = 1}^{n}\sum_{j = i + 1}^na_i\times a_j + \sum_{i = 1}^na_i^2 \\
&=\sum_{i = 1}^na_i(\sum_{j = i + 1}^na_j\times 2^{j - i + 1}) + \sum_{i = 1}^na_i^2\\
& 令 f(i) = \sum_{j = i + 1}^na_j\times 2^{j - i + 1}\\
&f(i - 1) = \sum_{j = i + 1}^na_j\times 2^{j - i}\\
&\to f(i) = 2\times f(i - 1) + a_i^2
\end{split}
\]
  • 时间复杂度:\(\mathcal{O}(n)\)
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

给定 \(n(1\le n\le 2e5)\) 和 \(m(1\le m \le 2e5)\) ,询问有多少满足长度为 \(n\) 的序列 \(A\)

  • \(1\le A_i \le M(i = 1,2,...,N)\)
  • \(A_{i + 1}\) 是 \(A_i\) 的倍数 \((i = 1,2,...,N-1)\)

注意到如果每次都有改变,顶多有 \(19\) 个数。调和级数一下是 \(\mathcal{O}(nlog\ n)\)

先计算dp方案数。

枚举有 \(i\) 个不同的数,对答案的贡献为 \(C(n-1,i-1)\times \sum_{j = 1}^m dp[i][j]\)

注意第一个肯定是第一个,无需考虑

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

给出 \(n(1\le n \le5000)\) 和 \(m(1\le m \le5000)\) ,询问有多少满足条件的长度为 \(n\) 的序列 \(A\)。

  • \(\sum_iA_i = m\)
  • \(xor(A_i) = 0\)
  • \(A_i>=0\)

D题开始,没有做出来,参考了高 Rank 的解法

显然每一位都有偶数个数选择。

\(f[i]\) 表示 \(n\) 个数和为 \(i\) 的方案数

\(f[i] += C(n,2\times j)\times f[(i -2\times j)/2]\)

是将之前和为\((i−2×j)/2\) 的 \(n\) 个数左移一位,并选\(2×j\) 个数最后一位为 \(1\)

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

有 \(n(1≤n≤2e5)\) 个点,选择 \(k\) 个为初始感染点,每秒沿边传播(扩张),求最快时间。


二分最快时间(距离)

\(f_u\ u\)子树内离他最近的感染点的距离

\(g_u\ u\)子树内离他最远的非感染点的距离

如果通过根节点中转能帮上 \(g_u\) 那么一定整个子树都已被覆盖

其他情况,如果 \(g_u=mid\) 那 \(u\) 必须成为初始感染点

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;
}

AtCoder Regular Contest 116 (A~F补题记录)的更多相关文章

  1. AtCoder Regular Contest 151补题

    AtCoder Regular Contest 151 A. Equal Hamming Distances 简单题,注意下答案需要字典序最小即可 #include<bits/stdc++.h& ...

  2. AtCoder Regular Contest 069 F Flags 二分,2-sat,线段树优化建图

    AtCoder Regular Contest 069 F Flags 二分,2-sat,线段树优化建图 链接 AtCoder 大意 在数轴上放上n个点,点i可能的位置有\(x_i\)或者\(y_i\ ...

  3. AtCoder Regular Contest 092

    AtCoder Regular Contest 092 C - 2D Plane 2N Points 题意: 二维平面上给了\(2N\)个点,其中\(N\)个是\(A\)类点,\(N\)个是\(B\) ...

  4. AtCoder Regular Contest 102

    AtCoder Regular Contest 102 C - Triangular Relationship 题意: 给出n,k求有多少个不大于n的三元组,使其中两两数字的和都是k的倍数,数字可以重 ...

  5. AtCoder Regular Contest 096

    AtCoder Regular Contest 096 C - Many Medians 题意: 有A,B两种匹萨和三种购买方案,买一个A,买一个B,买半个A和半个B,花费分别为a,b,c. 求买X个 ...

  6. AtCoder Regular Contest 097

    AtCoder Regular Contest 097 C - K-th Substring 题意: 求一个长度小于等于5000的字符串的第K小子串,相同子串算一个. K<=5. 分析: 一眼看 ...

  7. AtCoder Regular Contest 098

    AtCoder Regular Contest 098 C - Attention 题意 给定一个只包含"E","W"字符串,可以花一的花费使他们互相转换.选定 ...

  8. Atcoder regular Contest 073(C - Sentou)

    Atcoder regular Contest 073(C - Sentou) 传送门 每个人对开关的影响区间为a[i]--a[i]+t,因此此题即为将所有区间离散化后求所有独立区间的长度和 #inc ...

  9. AtCoder Regular Contest 061

    AtCoder Regular Contest 061 C.Many Formulas 题意 给长度不超过\(10\)且由\(0\)到\(9\)数字组成的串S. 可以在两数字间放\(+\)号. 求所有 ...

  10. AtCoder Regular Contest 094 (ARC094) CDE题解

    原文链接http://www.cnblogs.com/zhouzhendong/p/8735114.html $AtCoder\ Regular\ Contest\ 094(ARC094)\ CDE$ ...

随机推荐

  1. VS Code安装教程

    一.下载 1.官网 下载地址:https://code.visualstudio.com/Download 2.下载 根据自己电脑型号下载,此处以Windows为例. 二.安装 1.下载完成后,直接点 ...

  2. 第一次使用 GoLand 启动 运行 Go 项目

    一.开始之前确保已经安装 go语言环境 二.新建项目 三.选择项目路径 四.在该目录下手动创建 bin,src两个文件夹 bin 用来存放编译后的 .exe 文件 src 我们的工程的开发文件存放的点 ...

  3. 七天.NET 8操作SQLite入门到实战 - 第六天后端班级管理相关接口完善和Swagger自定义配置

    前言 在上一章节我们在后端框架中引入 SQLite-net ORM 并封装常用方法(SQLiteHelper),今天我们的任务是设计好班级管理相关的表.完善后端班级管理相关接口并对Swagger自定义 ...

  4. [CF1416F] Showing Off

    题目链接 如果把方向看做有向边,整个图是一个内向基环树. 所以考虑哪些点有可能放在基环树的非环部分上,当且仅当一个点周围有严格小于他的点. 由于图一定是二分图(黑白染色),没有奇环,所有偶环一定可以拆 ...

  5. 从根上理解elasticsearch(lucene)查询原理(2)-lucene常见查询类型原理分析

    大家好,我是蓝胖子,在上一节我提到要想彻底搞懂elasticsearch 慢查询的原因,必须搞懂lucene的查询原理,所以在上一节我分析了lucene查询的整体流程,除此以外,还必须要搞懂各种查询类 ...

  6. MySQL运维3-分库分表策略

    一.介绍 单库瓶颈:如果在项目中使用的都是单MySQL服务器,则会随着互联网及移动互联网的发展,应用系统的数据量也是成指数式增长,若采用单数据库进行存储,存在一下性能瓶颈: IO瓶颈:热点数据太多,数 ...

  7. ubuntu防火墙ufw基本使用方法

    ubuntu系统基本使用方法 防火墙 # 查看服务器防火墙状态 ufw status # 将防火墙设置为可用状态 ufw enable # 将防火墙设置为关闭状态 ufw disbale # 放行端口 ...

  8. ubuntu安装opencv的正确方法

    本文介绍的是如何安装ubuntu下C++接口的opencv 1.安装准备: 1.1安装cmake sudo apt-get install cmake 1.2依赖环境 sudo apt-get ins ...

  9. Sql整理

    1:数据库 数据库是以某种有组织的方式存储的数据集合. 保存有组织数据的容器,通常是一个文件或者一组文件. SQL 是Structured Query Language (结构化查询语言)的缩写. 2 ...

  10. Python——第三章:函数的定义

    函数的定义: 对某一个特定的功能或者代码块进行封装. 在需要使用该功能的时候直接调用即可 格式: def 函数的名字(): 被封装的功能或者代码块->函数体 调用: 函数的名字() 使用函数的好 ...