2023牛客暑期多校训练营3 ABDHJ
A
题解
知识点:数学。
当 \(x = 0\) 时,当且仅当 \(y = 0\) 可行。
当 \(x \neq 0\) 时,一定可行,答案为 \(|x-y|\) 。
时间复杂度 \(O(1)\)
空间复杂度 \(O(1)\)
代码
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
string x, y;
cin >> x >> y;
ll X = 0, Y = 0;
for (int i = 0;i < x.size();i++) (X <<= 1) |= x[i] - '0';
for (int i = 0;i < y.size();i++) (Y <<= 1) |= y[i] - '0';
if (X == 0) {
if (Y == 0) cout << 0 << '\n';
else cout << -1 << '\n';
}
else cout << abs(X - Y) << '\n';
return 0;
}
B
题解
知识点:排列组合,计数dp。
注意到,最后的排列一定是一段小数 \([1,n]\) ,一段大数 \([n+1,2n]\) 交替。
考虑设 \(f_{i,j,0/1}\) 表示填了 \(i\) 个小数, \(j\) 个大数,最后一段是小数或大数段的合法方案数(注意这里没包括最后一个错误的牌),有转移方程:
if (k <= i) f[i][j][0] += f[i - k][j][1] * CNM::C(n - i + k, k);
if (k <= j) f[i][j][1] += f[i][j - k][0] * CNM::C(n - j + k, k);
其中 \(k\) 为最后一段数字的个数。
统计答案时,我们考虑每个位置猜对时产生的贡献。对于前 \(i\) 个小数, \(j\) 个大数猜对时的方案数量为:
\]
此时的所有方案,一定会在第 \(i+j\) 的位置产生一张猜对的牌的贡献。
最后我们需要加上每个排列最后一张错误的牌,共 \((2n)! - (f_{n,n,0} + f_{n,n,1})\) 种方案会产生一张错误的牌。
时间复杂度 \(O(n^3)\)
空间复杂度 \(O(n^2)\)
代码
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
struct Modint {
static int P;
int val;
Modint(int _val = 0) :val(_val %P) { format(); }
Modint(ll _val) :val(_val %P) { format(); }
//if val in [-P,2P)
Modint &format() {
if (val < 0) val += P;
if (val >= P) val -= P;
return *this;
}
Modint inv()const { return qpow(*this, P - 2); }
Modint &operator+=(const Modint &x) { val += x.val;return format(); }
Modint &operator-=(const Modint &x) { val -= x.val;return format(); }
Modint &operator*=(const Modint &x) { val = 1LL * val * x.val % P;return *this; }
Modint &operator/=(const Modint &x) { return *this *= x.inv(); }
friend Modint operator-(const Modint &x) { return { -x.val }; }
friend Modint operator+(Modint a, const Modint &b) { return a += b; }
friend Modint operator-(Modint a, const Modint &b) { return a -= b; }
friend Modint operator*(Modint a, const Modint &b) { return a *= b; }
friend Modint operator/(Modint a, const Modint &b) { return a /= b; }
friend Modint qpow(Modint a, ll k) {
Modint ans = 1;
while (k) {
if (k & 1) ans = ans * a;
k >>= 1;
a = a * a;
}
return ans;
}
friend istream &operator>>(istream &is, Modint &x) {
ll _x;
is >> _x;
x = { _x };
return is;
}
friend ostream &operator<<(ostream &os, const Modint &x) { return os << x.val; }
};
/// 自动取模整数,O(logk)快速幂、O(logP)逆元、O(1)运算
int P;
namespace CNM {
const int N = 3e2 + 7;
int c[N][N];
void init(int n) {
for (int i = 0;i <= n;i++)
for (int j = 0;j <= i;j++)
c[i][j] = 0 < j && j < i ? (c[i - 1][j - 1] + c[i - 1][j]) % P : 1;
}
int C(int n, int m) {
if (n == m && m == -1) return 1; //* 隔板法特判
if (n < m || m < 0) return 0;
return c[n][m];
}
}
int Modint::P = 1e9 + 7;
Modint f[307][307][2];
Modint fact[607];
bool solve() {
int n;
cin >> n >> P;
Modint::P = P;
CNM::init(n);
fact[0] = 1;
for (int i = 1;i <= 2 * n;i++) fact[i] = fact[i - 1] * i;
for (int i = 0;i <= n;i++) for (int j = 0;j <= n;j++) f[i][j][0] = f[i][j][1] = 0;
f[0][0][0] = f[0][0][1] = 1;
Modint ans = 0;
for (int i = 0;i <= n;i++) {
for (int j = 0;j <= n;j++) {
for (int k = 1;k <= n;k++) {
if (k <= i) f[i][j][0] += f[i - k][j][1] * CNM::C(n - i + k, k);
if (k <= j) f[i][j][1] += f[i][j - k][0] * CNM::C(n - j + k, k);
}
if (i + j > 0) ans += (f[i][j][0] + f[i][j][1]) * fact[2 * n - i - j];// 第i+j张牌正确时的贡献 = 至少在i+j前正确时的方案数 * 1
}
}
ans += fact[2 * n]; // 所有排列都会有一张错误的牌
ans -= f[n][n][0] + f[n][n][1]; // 除了全对的排列
cout << ans << '\n';
return true;
}
int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int t = 1;
cin >> t;
while (t--) {
if (!solve()) cout << -1 << '\n';
}
return 0;
}
D
题解
知识点:位运算,数学。
注意到,最终只有全 \(0\) 或 \(1\) 的情况才是合法的。因此考虑从这两种情况逆推,不妨考虑全 \(0\) 情况。
我们发现,无论如何操作,所有行都和第一行或者第一行取反一致(对列一样,这里只需要考虑行即可)。因此,一开始先判断矩阵是否合法,再进行操作次数的计算。
对于操作次数, 最小值为第一行的 \(0,1\) 最少数量加第一列的 \(0,1\) 最少数量。因为,我们先对行操作把一行对齐,此时所有行都是一样的,在对列操作即可。对行操作的次数,即第一列的 \(0,1\) 最少数量;之后,对列操作的次数,即第一行的 \(0,1\) 最少数量。
时间复杂度 \(O(n^2)\)
空间复杂度 \(O(n^2)\)
代码
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
int a[2007][2007];
int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int n;
cin >> n;
for (int i = 1;i <= n;i++)
for (int j = 1;j <= n;j++) {
char ch;
cin >> ch;
a[i][j] = ch == '1';
}
for (int i = 1;i <= n;i++) {
bool ok = 1, f = a[i][1] == a[1][1];
for (int j = 1;j <= n;j++) ok &= (a[i][j] == a[1][j]) == f;
if (!ok) {
cout << -1 << '\n';
return 0;
}
}
array<int, 4> cnt{};
for (int i = 1;i <= n;i++) {
if (a[1][i]) cnt[1]++;
else cnt[0]++;
if (a[i][1]) cnt[2 + 1]++;
else cnt[2 + 0]++;
}
cout << min(cnt[0], cnt[1]) + min(cnt[2], cnt[3]) << '\n';
return 0;
}
H
题解
知识点:数论。
显然,操作可以使得数字任意分配,但总和不变,因此考虑总和能否构造为质数序列。
哥德巴赫猜想:对于一个大于等于 \(4\) 的偶数,总能分为两个质数之和。(人类探索范围没有反例)
分类讨论:
当 \(n=1\) 时,判断是否为质数即可。
当 \(n=2\) 时,若 \(sum < 4\) 则无解。
否则,若 \(sum\) 是奇数,那么 \(sum-2\) 是质数即可;若 \(sum\) 是偶数,根据哥德巴赫猜想一定有解。
当 \(n \geq 3\) 时,若 \(sum < 2n\) 则无解。
否则,若 \(sum\) 是奇数,前面放 \(n-3\) 个 \(2\) 和 \(1\) 个 \(3\) ,最后还剩大于等于 \(4\) 的偶数,根据哥德巴赫猜想一定有解 ;若 \(sum\) 是偶数,根据哥德巴赫猜想一定有解。
综上 \(sum \geq 2n\) 一定有解。
时间复杂度 \(O(n)\)
空间复杂度 \(O(1)\)
代码
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
bool isPrime(int n) {
if (n == 2) return 1;
if (n == 1) return 0;
for (int i = 2;i * i <= n;i++) if (!(n % i)) return 0;
return 1;
}
/// 试除法,O(n^(1/2)),枚举[1,sqrt(n)]作为质因子判断素数
int a[1007];
int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int n;
cin >> n;
ll sum = 0;
for (int i = 1;i <= n;i++) cin >> a[i], sum += a[i];
if (n == 1) {
if (isPrime(a[1])) cout << "Yes" << '\n';
else cout << "No" << '\n';
return 0;
}
if (n == 2) {
if (sum >= 2 * n) {
if (sum & 1) {
if (isPrime(sum - 2)) cout << "Yes" << '\n';
else cout << "No" << '\n';
}
else cout << "Yes" << '\n';
}
else cout << "No" << '\n';
return 0;
}
if (sum >= 2 * n) {
if (sum & 1) {
if (isPrime(sum - (n - 1) * 2)) cout << "Yes" << '\n';
else if (sum - (n - 3) * 2 - 3 >= 4) cout << "Yes" << '\n';
else cout << "No" << '\n';
}
else cout << "Yes" << '\n';
}
else cout << "No" << '\n';
return 0;
}
J
题解
知识点:拓扑排序。
显然,若原图是dag,拓扑序就是最终结果。
否则,一定需要两个排名序列,直接输出 \(1\) 到 \(n\) 正序反序即可。
实现用一次拓扑排序即可完成判环和拓扑序。
时间复杂度 \(O(n+m)\)
空间复杂度 \(O(n+m)\)
代码
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 1e6 + 7;
int n, m;
vector<int> g[N];
int deg[N];
int ans[N], cnt;
queue<int> q;
void toposort() {
cnt = 0;
for (int i = 1;i <= n;i++) deg[i] = 0;
for (int i = 1;i <= n;i++) for (auto v : g[i]) deg[v]++;
for (int i = 1;i <= n;i++) if (!deg[i]) q.push(i);
while (!q.empty()) {
int u = q.front();
q.pop();
ans[++cnt] = u;
for (auto v : g[u]) {
deg[v]--;
if (!deg[v]) q.push(v);
}
}
}
int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin >> n >> m;
for (int i = 1;i <= m;i++) {
int u, v;
cin >> u >> v;
g[u].push_back(v);
}
toposort();
if (cnt == n) {
cout << 1 << '\n';
for (int i = 1;i <= n;i++) cout << ans[i] << " \n"[i == n];
}
else {
cout << 2 << '\n';
for (int i = 1;i <= n;i++) cout << i << " \n"[i == n];
for (int i = 1;i <= n;i++) cout << n + 1 - i << " \n"[i == n];
}
return 0;
}
2023牛客暑期多校训练营3 ABDHJ的更多相关文章
- 2019牛客暑期多校训练营(第五场)G - subsequeue 1 (一题我真的不会的题)
layout: post title: 2019牛客暑期多校训练营(第五场)G - subsequeue 1 (一题我真的不会的题) author: "luowentaoaa" c ...
- 2021牛客暑期多校训练营3 J 思维
传送门 J-Counting Triangles_2021牛客暑期多校训练营3 (nowcoder.com) 题目 Goodeat finds an undirected complete graph ...
- B-xor_2019牛客暑期多校训练营(第四场)
题意 给出n个数组(每组数个数不定),m个询问 l, r, x 序号在区间\([l,r]\)的每个数组是否都可以取出任意个数异或出x 题解 判断一个数组能否异或出x,是简单的线性基问题 判断多个线性基 ...
- 2019牛客暑期多校训练营(第九场)A:Power of Fibonacci(斐波拉契幂次和)
题意:求Σfi^m%p. zoj上p是1e9+7,牛客是1e9: 对于这两个,分别有不同的做法. 前者利用公式,公式里面有sqrt(5),我们只需要二次剩余求即可. 后者mod=1e9,5才 ...
- 2019牛客暑期多校训练营(第一场)A题【单调栈】(补题)
链接:https://ac.nowcoder.com/acm/contest/881/A来源:牛客网 题目描述 Two arrays u and v each with m distinct elem ...
- 2019牛客暑期多校训练营(第一场) B Integration (数学)
链接:https://ac.nowcoder.com/acm/contest/881/B 来源:牛客网 Integration 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 5242 ...
- 2019牛客暑期多校训练营(第一场) A Equivalent Prefixes ( st 表 + 二分+分治)
链接:https://ac.nowcoder.com/acm/contest/881/A 来源:牛客网 Equivalent Prefixes 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/ ...
- 2019牛客暑期多校训练营(第二场)F.Partition problem
链接:https://ac.nowcoder.com/acm/contest/882/F来源:牛客网 Given 2N people, you need to assign each of them ...
- 2019牛客暑期多校训练营(第八场)E.Explorer
链接:https://ac.nowcoder.com/acm/contest/888/E来源:牛客网 Gromah and LZR have entered the fifth level. Unli ...
- 2019牛客暑期多校训练营(第一场)A Equivalent Prefixes(单调栈/二分+分治)
链接:https://ac.nowcoder.com/acm/contest/881/A来源:牛客网 Two arrays u and v each with m distinct elements ...
随机推荐
- spring--集成RocketMQ
在Spring Boot中集成RocketMQ通常涉及以下步骤: 1. **添加依赖**:首先,需要在项目的`pom.xml`文件中添加RocketMQ的Spring Boot Starter依赖. ...
- Nacos源码 (3) 注册中心
本文将从一个服务注册示例入手,通过阅读客户端.服务端源码,分析服务注册.服务发现原理. 使用的2.0.2的版本. 客户端 创建NacosNamingService对象 NacosNamingServi ...
- 8. exporter
一.已经实现的收集器 1.1 可收集的内存指标 1.2 可收集的jetty指标 二.自定义收集 2.1 summer 2.2 histogram 三.架构设计 exporter作为Prometheus ...
- Shell-函数-function
- [转帖]/etc/security/limits.conf 详解与配置
https://www.cnblogs.com/operationhome/p/11966041.html 一. /etc/security/limits.conf 详解 /etc/security/ ...
- [转帖]Lightning 实操指南
2.2.2 Lightning 实操指南 这一节将介绍如何使用 Lightning 导入数据的实操 2.2.2.1 TiDB Lightning 快速开始 注意 TiDB Lightning 运行后, ...
- kafka的学习之一_带SASL鉴权的集群安装与启动
kafka的学习之一_带SASL鉴权的集群安装与启动 背景 想开始一段新的里程. 可能会比现在累, 可能会需要更多的学习和努力. kafka可能就是其中之一. 自己之前总是畏缩不前. 不想面对很多压力 ...
- [转帖]「Linux性能调优」磁盘I/O队列调度策略
https://zhuanlan.zhihu.com/p/450329513 傻瓜化说明 简单地说,对于磁盘I/O,Linux提供了cfq, deadline和noop三种调度策略 cfq: 这个名字 ...
- buildkit的简单学习与使用
下载 需要注意本文学习了很多如下网站的内容: https://zhuanlan.zhihu.com/p/366671300 # 第一步下载资源 https://github.com/moby/buil ...
- SMEE 国内最新光刻机