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 ...
随机推荐
- 基于python+django的家教预约网站-家教信息管理系统设计与实现
该系统是基于python+django开发的家教预约网站.是给师妹做的课程作业.大家在学习过程中,遇到问题可以在github给作者留言. 效果演示 前台地址: http://jiajiao.gitap ...
- SV task and function
内容 system verilog过程语句:自增和自减操作符 逻辑比较操作符 逻辑值为1bit inside语句 变量类型转换 强制类型转换:$cast() 变量位宽转换 变量符号位转换 for循环语 ...
- vscode - Prettier插件 统一代码风格规范,保存自动格式化代码
安装 Prettier - Code formatter prettier安装完毕,使用shift+alt+f就可格式化代码. 如果需要自动保存,要在系统设置中增加"editor.forma ...
- SQLServer的varchar与nvarchar的学习之二
SQLServer的varchar与nvarchar的学习之二 背景 昨天简单总结了多种数据库 varchar和nvarchar的区别与关系 今天想着能够分析一下数据库文件. 计划使用winhex 查 ...
- [转帖]centos7离线安装postgresql13
https://www.cnblogs.com/summer-88/p/15341918.html 在一台可以联网的centos上安装postgresql源 yum install -y https: ...
- [转帖]KingbaseES和Oracle数据类型的映射表
随着数据库国产化的进程,Oracle向KingbaseES数据库的数据迁移需求也越来越多.数据库之间数据迁移的时候,首先遇到的,并且也是最重要的,就是数据类型之间的转换. 下表为KingbaseES和 ...
- [转帖]@Autowired 和 @Resource 的区别
@Autowired 和 @Resource 的区别 默认注入方式不同 @Autowired 默认的注入方式为byType(根据类型进行匹配),也就是说会优先根据接口类型去匹配并注入 Bean (接口 ...
- Oracle 修改参数
alter system set sga_max_size=30720M scope=spfile; alter system set sga_target=30720M; alter system ...
- 如何优雅的写 css 代码
CSS(全称 Cascading Style Sheets,层叠样式表)为开发人员提供声明式的样式语言,是前端必备的技能之一,基于互联网上全面的资料和简单易懂的语法,CSS 非常易于学习,但其知识点广 ...
- vue中render函数使用attrs绑定id、class、style、事件(5)
1.h函数的三个参数 第一个参数是必须的. 类型:{String | Object | Function} 一个 HTML 标签名.一个组件.一个异步组件.或一个函数式组件. 是要渲染的html标签. ...