比赛链接

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. 在Windows 版的Chrome中切换标签页

    按住Ctrl+tab键之后使用page up/ page down键左右移动!

  2. Java-Enum常量特定方法

    OnJava8-Enum-常量特定方法 用枚举实现责任链模式 责任链(Chain Of Responsibility)设计模式先创建了一批用于解决目标问题的不同方法,然后将它们连成一条"链& ...

  3. MyBatis02:CRUD操作

    CRUD操作 namespace 这个是命名空间,不可缺少,更不能写错 配置文件中namespace中的名称为对应Mapper接口或者Dao接口的全限定类名,完整包名,必须一致! Select(用于查 ...

  4. [转帖]Linux ps -o 查看进程启动时间

    https://www.cnblogs.com/apink/p/17572435.html 时间参数 如下表 参数  含义 start 显示进程启动时间的简短格式.通常,它会显示日期时间中的月-日 或 ...

  5. 阿里云IPV6 创建虚拟机的过程

    阿里云IPV6 创建虚拟机的过程 背景 IPV6 已经越来越广泛的应用. 想在外网开通一下IPV6,发现还有一些坑. 这里总结一下. 备忘. 开通方式 1. 登录阿里云的控制台, 打开云服务器ECS的 ...

  6. [转帖]Web技术(七):如何使用并实现MQTT 消息订阅-发布模型?

    文章目录 一.什么是发布-订阅消息模型? 二.订阅-发布消息模型有哪些应用? 2.1 应用于IP 物联网络中的消息传递 2.2 应用于操作系统进程间的消息传递 2.3 应用于MESH 自组网中的消息传 ...

  7. [转帖]INTEL MLC(Memory Latency Checker)介绍

    https://zhuanlan.zhihu.com/p/359823092 在定位机器性能问题的时候,有时会觉得机器莫名其妙地跑的慢,怎么也看不出来问题.CPU频率也正常,程序热点也没问题,可就是慢 ...

  8. [转帖]20个常用的Linux工具命令

    https://www.cnblogs.com/codelogs/p/16060113.html 简介# 网上有很多辅助开发的小工具,如base64,md5之类的,但这些小工具其实基本都可以用Linu ...

  9. SAP FICO 前台财务过账、预制功能分开

    最近遇到一个变态要求,FB01 等涉及过账功能 要求根据'权限'判断用户是否有过账的功能.以下实现会有遗漏场景: 实现:hide 'SAVE'按钮 (ok_code = 'BU'). 根据状态栏设置' ...

  10. vm-storage在全部都是旧metric情况下的写入性能测试

    作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢! cnblogs博客 zhihu Github 公众号:一本正经的瞎扯 接上篇:测试所有metric都是存在过的metric的情况 ...