比赛链接

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\) 个大数猜对时的方案数量为:

\[(f_{i,j,0} + f_{i,j,1}) \cdot (2n-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\) 的偶数,总能分为两个质数之和。(人类探索范围没有反例)

分类讨论:

  1. 当 \(n=1\) 时,判断是否为质数即可。

  2. 当 \(n=2\) 时,若 \(sum < 4\) 则无解。

    否则,若 \(sum\) 是奇数,那么 \(sum-2\) 是质数即可;若 \(sum\) 是偶数,根据哥德巴赫猜想一定有解。

  3. 当 \(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的更多相关文章

  1. 2019牛客暑期多校训练营(第五场)G - subsequeue 1 (一题我真的不会的题)

    layout: post title: 2019牛客暑期多校训练营(第五场)G - subsequeue 1 (一题我真的不会的题) author: "luowentaoaa" c ...

  2. 2021牛客暑期多校训练营3 J 思维

    传送门 J-Counting Triangles_2021牛客暑期多校训练营3 (nowcoder.com) 题目 Goodeat finds an undirected complete graph ...

  3. B-xor_2019牛客暑期多校训练营(第四场)

    题意 给出n个数组(每组数个数不定),m个询问 l, r, x 序号在区间\([l,r]\)的每个数组是否都可以取出任意个数异或出x 题解 判断一个数组能否异或出x,是简单的线性基问题 判断多个线性基 ...

  4. 2019牛客暑期多校训练营(第九场)A:Power of Fibonacci(斐波拉契幂次和)

    题意:求Σfi^m%p. zoj上p是1e9+7,牛客是1e9:  对于这两个,分别有不同的做法. 前者利用公式,公式里面有sqrt(5),我们只需要二次剩余求即可.     后者mod=1e9,5才 ...

  5. 2019牛客暑期多校训练营(第一场)A题【单调栈】(补题)

    链接:https://ac.nowcoder.com/acm/contest/881/A来源:牛客网 题目描述 Two arrays u and v each with m distinct elem ...

  6. 2019牛客暑期多校训练营(第一场) B Integration (数学)

    链接:https://ac.nowcoder.com/acm/contest/881/B 来源:牛客网 Integration 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 5242 ...

  7. 2019牛客暑期多校训练营(第一场) A Equivalent Prefixes ( st 表 + 二分+分治)

    链接:https://ac.nowcoder.com/acm/contest/881/A 来源:牛客网 Equivalent Prefixes 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/ ...

  8. 2019牛客暑期多校训练营(第二场)F.Partition problem

    链接:https://ac.nowcoder.com/acm/contest/882/F来源:牛客网 Given 2N people, you need to assign each of them ...

  9. 2019牛客暑期多校训练营(第八场)E.Explorer

    链接:https://ac.nowcoder.com/acm/contest/888/E来源:牛客网 Gromah and LZR have entered the fifth level. Unli ...

  10. 2019牛客暑期多校训练营(第一场)A Equivalent Prefixes(单调栈/二分+分治)

    链接:https://ac.nowcoder.com/acm/contest/881/A来源:牛客网 Two arrays u and v each with m distinct elements ...

随机推荐

  1. spring--集成RocketMQ

    在Spring Boot中集成RocketMQ通常涉及以下步骤: 1. **添加依赖**:首先,需要在项目的`pom.xml`文件中添加RocketMQ的Spring Boot Starter依赖. ...

  2. Nacos源码 (3) 注册中心

    本文将从一个服务注册示例入手,通过阅读客户端.服务端源码,分析服务注册.服务发现原理. 使用的2.0.2的版本. 客户端 创建NacosNamingService对象 NacosNamingServi ...

  3. 8. exporter

    一.已经实现的收集器 1.1 可收集的内存指标 1.2 可收集的jetty指标 二.自定义收集 2.1 summer 2.2 histogram 三.架构设计 exporter作为Prometheus ...

  4. Shell-函数-function

  5. [转帖]/etc/security/limits.conf 详解与配置

    https://www.cnblogs.com/operationhome/p/11966041.html 一. /etc/security/limits.conf 详解 /etc/security/ ...

  6. [转帖]Lightning 实操指南

    2.2.2 Lightning 实操指南 这一节将介绍如何使用 Lightning 导入数据的实操 2.2.2.1 TiDB Lightning 快速开始 注意 TiDB Lightning 运行后, ...

  7. kafka的学习之一_带SASL鉴权的集群安装与启动

    kafka的学习之一_带SASL鉴权的集群安装与启动 背景 想开始一段新的里程. 可能会比现在累, 可能会需要更多的学习和努力. kafka可能就是其中之一. 自己之前总是畏缩不前. 不想面对很多压力 ...

  8. [转帖]「Linux性能调优」磁盘I/O队列调度策略

    https://zhuanlan.zhihu.com/p/450329513 傻瓜化说明 简单地说,对于磁盘I/O,Linux提供了cfq, deadline和noop三种调度策略 cfq: 这个名字 ...

  9. buildkit的简单学习与使用

    下载 需要注意本文学习了很多如下网站的内容: https://zhuanlan.zhihu.com/p/366671300 # 第一步下载资源 https://github.com/moby/buil ...

  10. SMEE 国内最新光刻机