NZOJ 模拟赛8
T1 布尔(CF2030C)
爱丽丝和鲍勃正在玩一个游戏。游戏中有一个由 n 个布尔值组成的列表,每个布尔值要么为真,要么为假,以长度为 n 的二进制字符串表示(其中 1 表示为真,0 表示为假)。最初,布尔值之间没有运算符。
爱丽丝和鲍勃将轮流在布尔之间放置 or 或 and,爱丽丝先放。因此,由于有 n 个布尔值,游戏将由 n-1 个回合组成。爱丽丝的目标是最后的语句结果为 "真",而鲍勃的目标是最后的语句结果为 "假"。给定布尔值列表,判断如果双方都以最佳方式下棋,爱丽丝是否会赢。
要对最终表达式进行求值,请重复执行以下步骤,直到该语句只包含一个 "true "或 "false":
- 如果语句中包含 and 运算符,则任选一个,并用其求值替换其周围的子表达式。
- 否则,语句包含 or 运算符。任选一个,并用其运算结果替换其周围的子表达式。
例如,表达式 true 或 false 和 false 的运算结果为 true or(false and false)= true 或 false = true。可以看出,任何复合语句的结果都是唯一的。
二进制字符串是仅由字符 0 和 1 组成的字符串。
经过尝试容易发现,当存在连续两个 \(\texttt{TRUE}\) 时,先手往中间放一个 \(\texttt{or}\),后手无论如何放置,先手在另一侧放置一个 \(\texttt{or}\) 一定可以保证结果为 \(\texttt{TRUE}\);如果头尾存在 \(\texttt{TRUE}\),那么先手直接放置 \(\texttt{or}\) 就可以必胜;反之必败。
参考代码
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
int n, m;
char s[N];
void solve()
{
cin >> n;
cin >> s;
for (int i = 1; i < n; i ++ )
if (s[i - 1] == '1' && s[i] == '1')
return puts("YES"), void();
if (s[0] == '1' || s[n - 1] == '1') return puts("YES"), void();
puts("NO");
}
int main()
{
int T = 1;
cin >> T;
while (T -- ) solve();
return 0;
}
T2 Max × Sum(ABC376E)
给你长度为 N 的序列: A = (A1, A2, ..., AN) 和 B = (B1, B2, ..., BN) 。
设 S 是大小为 K 的 {1, 2, ..., N} 的子集。求以下表达式的最小可能值:\[\displaystyle \left(\max_{i \in S} A_i\right) \times \left(\sum_{i \in S} B_i\right)
\]
考虑贪心,按照 \(A_i\) 的大小排序,如果可以确定 \(\max\limits_{i \in S} A_i\),我们发现 \(\sum\limits_{i \in S} B_i\) 也是唯一确定的,一定是前 \(i\) 个元素的前 \(k\) 小值的和,否则不优,因为我们想要乘积最小,因此我们维护一个优先队列存储前 \(k\) 小值即可。
参考代码
#include<bits/stdc++.h>
using namespace std;
typedef pair<int, int> PII;
typedef long long ll;
const int N = 2e5 + 10;
int n, k, a[N], b[N];
PII c[N];
int main()
{
cin >> n >> k;
for (int i = 1; i <= n; i ++ ) cin >> a[i];
for (int i = 1; i <= n; i ++ ) cin >> b[i];
for (int i = 1; i <= n; i ++ ) c[i] = {a[i], b[i]};
sort(c + 1, c + n + 1);
priority_queue<ll> heap;
ll ans = 1e18, sum = 0;
for (int i = 1; i <= k; i ++ ) heap.push(c[i].second), sum += c[i].second;
ans = min(ans, sum * c[k].first);
for (int i = k + 1; i <= n; i ++ )
{
ll t = heap.top();
if (t > c[i].second) heap.pop(), sum -= t, heap.push(c[i].second), sum += c[i].second;
ans = min(ans, sum * c[i].first);
}
cout << ans << endl;
return 0;
}
T3 竞赛(CF2024D)
现在已经是 3024 年,问题的创意早已枯竭,奥林匹克竞赛现在以修改后的个人形式进行。奥林匹克竞赛由 n 个问题组成,编号从 1 到 n 。其中第 i 个问题有自己的分数 ai 和一定的参数 bi (1 ≤ bi ≤ n)。
最初,测试系统会给参与者第 1 个问题。当参与者得到第 i 个问题时,他们有两个选择:
- 他们可以提交问题并获得 ai 分;
- 他们可以跳过这个问题,在这种情况下,他们将永远无法提交这个问题。
然后,测试系统会从索引为 j 的问题中为参与者选择下一个问题,这样,参与者就可以提交下一个问题:
- 如果他提交了第 i 个问题,系统就会查看索引为 j < i 的问题;
- 如果他跳过了第 i 个问题,则会查看索引为 j ≤ bi 的问题。
在这些问题中,它会选择一个索引最大的问题,这个索引以前没有给过参与者(他以前既没有提交也没有跳过这个问题)。如果没有这样的问题,则该参赛者的比赛结束,其成绩等于所有提交问题的分数总和。特别是,如果参赛者提交了第一个问题,那么他们的比赛就结束了。需要注意的是,参赛者最多只能收到每个问题 1 次。
Prokhor 已经为奥林匹克竞赛做了充分准备,现在他可以提交任何问题。请帮助他确定他能获得的最高分数。
我们发现如果可以提交第 \(i\) 个问题,那么一定可以提交所有 \(1 \le j < i\) 中未被跳过的问题 \(j\),因此,我们的问题转化为了我们能够提交问题 \(i\),并且前 \(i\) 个问题我们跳过的分数为多少。
考虑最短路模型,我们如果跳过了问题 \(i\),那么我们失去的分数为 \(a_i\),但是我们也因此可以回答 \(b_i\) 题前的所有题,我们想要分数尽可能高,那么就是想办法尽可能的能够回答更多的问题,所以我们给 \(i \to b_i\) 连一条权值为 \(a_i\) 的有向边。由于所有的问题,如果我们能够回答第 \(i\) 个问题,我们都可以先不考虑第 \(i\) 个问题而考虑更前面的问题,因此我们给 \(i \to i - 1\) 连一条权值为 \(0\) 的有向边,代表我可以考虑这个问题更前列的问题,跑一次最短路,就可以知道我想回答 \(i\) 问题前所有的问题需要的代价,注意到所有被跳过的问题只会被考虑一次,否则到达同一个点不满足最短路模型,因此我们的答案为 \(i\) 问题前所有问题的分数减去到达 \(i\) 问题的代价。
参考代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll, int> PII;
const int N = 4e5 + 10;
int n, a[N], b[N];
int h[N], e[N << 1], w[N << 1], ne[N << 1], idx;
ll dist[N];
bool st[N];
void add(int a, int b, int c)
{
e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++ ;
}
void dijkstra()
{
priority_queue<PII, vector<PII>, greater<PII>> heap;
memset(dist, 0x3f, sizeof dist);
dist[1] = 0, heap.push({0, 1});
while (heap.size())
{
PII t = heap.top();
heap.pop();
ll d = t.first;
int u = t.second;
if (st[u]) continue;
st[u] = 1;
for (int i = h[u]; ~i; i = ne[i])
{
int j = e[i];
if (d + w[i] < dist[j])
{
dist[j] = d + w[i];
if (!st[j]) heap.push({dist[j], j});
}
}
}
}
int main()
{
cin >> n;
ll sum = 0, ans = 0;
memset(h, -1, sizeof h);
for (int i = 1; i <= n; i ++ ) cin >> a[i];
for (int i = 1; i <= n; i ++ )
{
cin >> b[i];
if (i - 1) add(i, i - 1, 0);
add(i, b[i], a[i]);
}
dijkstra();
for (int i = 1; i <= n; i ++ )
{
sum += a[i];
ans = max(sum - dist[i], ans);
}
cout << ans << endl;
return 0;
}
T4 三队划分(ABC375E)
有 N 人分成三个小组。
人数编号为 1, 2, ..., N ,团队编号为 1, 2, 3 。目前, i 属于 Ai 小组。
每个人都有一个名为强度的值, i 的强度为 Bi 。一个团队的强度被定义为其成员强度的总和。
确定是否可能有零个或更多的人交换团队,从而使所有团队的实力相等。如果可能,求最少需要多少人换队才能达到这个目的。
除了队伍 1 、 2 、 3 以外,您不能创建新的团队。
3 ≤ N ≤ 100
Ai ∈ {1, 2, 3}
对于每个 x ∈ {1, 2, 3} ,都存在一些 i 使得 Ai = x 。
1 ≤ Bi,且所有 Bi 的和不超过 1500。
所有输入值都是整数。
考虑动态规划,首先对于所有的人如果强度之和不是 \(3\) 的倍数,那么一定不存在结果。
类似于背包问题,我们记 \(dp[i][j][k]\) 表示考虑前 \(i\) 个人,队伍 \(1\) 的力量和为 \(j\),队伍 \(2\) 的力量和为 \(k\),队伍 \(3\) 的力量和可以被 \(i, j\) 唯一确定。
对于下一个状态,我们考虑将第 \(i + 1\) 个人分别插入进 \(3\) 支队伍,如果这个人本来就在这个队伍,那么贡献为 \(0\),否则贡献为 \(1\)。
例如第 \(i + 1\) 个人在第 \(1\) 支队伍,那么有:
\]
\]
\]
他们分别为插入第 \(1, 2, 3\) 支队伍的代价转移,对所有合法的状态取一个 \(\min\) 即可,初始化 \(dp\) 数组为极大值,如果结束后该状态不存在则输出 \(-1\),否则答案为最小操作次数。
参考代码
#include<bits/stdc++.h>
using namespace std;
const int N = 510, M = 110;
int n, sum, a[N], b[N], dp[M][N][N];
int main()
{
memset(dp, 0x3f, sizeof dp);
cin >> n;
for (int i = 1; i <= n; i ++ ) cin >> a[i] >> b[i], sum += b[i];
if (sum % 3) return puts("-1"), 0;
sum /= 3, dp[0][0][0] = 0;
for (int i = 1; i <= n; i ++ )
{
for (int j = 0; j <= sum; j ++ )
{
for (int k = 0; k <= sum; k ++ )
{
if (a[i] == 1)
{
if (j + b[i] <= sum) dp[i][j + b[i]][k] = min(dp[i][j + b[i]][k], dp[i - 1][j][k]);
if (k + b[i] <= sum) dp[i][j][k + b[i]] = min(dp[i][j][k + b[i]], dp[i - 1][j][k] + 1);
dp[i][j][k] = min(dp[i][j][k], dp[i - 1][j][k] + 1);
}
else if (a[i] == 2)
{
if (j + b[i] <= sum) dp[i][j + b[i]][k] = min(dp[i][j + b[i]][k], dp[i - 1][j][k] + 1);
if (k + b[i] <= sum) dp[i][j][k + b[i]] = min(dp[i][j][k + b[i]], dp[i - 1][j][k]);
dp[i][j][k] = min(dp[i][j][k], dp[i - 1][j][k] + 1);
}
else
{
if (j + b[i] <= sum) dp[i][j + b[i]][k] = min(dp[i][j + b[i]][k], dp[i - 1][j][k] + 1);
if (k + b[i] <= sum) dp[i][j][k + b[i]] = min(dp[i][j][k + b[i]], dp[i - 1][j][k] + 1);
dp[i][j][k] = min(dp[i][j][k], dp[i - 1][j][k]);
}
}
}
}
if (dp[n][sum][sum] == 0x3f3f3f3f) puts("-1");
else cout << dp[n][sum][sum];
return 0;
}
NZOJ 模拟赛8的更多相关文章
- NOIP模拟赛20161022
NOIP模拟赛2016-10-22 题目名 东风谷早苗 西行寺幽幽子 琪露诺 上白泽慧音 源文件 robot.cpp/c/pas spring.cpp/c/pas iceroad.cpp/c/pas ...
- NOI模拟赛 Day1
[考完试不想说话系列] 他们都会做呢QAQ 我毛线也不会呢QAQ 悲伤ING 考试问题: 1.感觉不是很清醒,有点困╯﹏╰ 2.为啥总不按照计划来!!! 3.脑洞在哪里 4.把模拟赛当作真正的比赛,紧 ...
- NOIP第7场模拟赛题解
NOIP模拟赛第7场题解: 题解见:http://www.cqoi.net:2012/JudgeOnline/problemset.php?page=13 题号为2221-2224. 1.car 边界 ...
- contesthunter暑假NOIP模拟赛第一场题解
contesthunter暑假NOIP模拟赛#1题解: 第一题:杯具大派送 水题.枚举A,B的公约数即可. #include <algorithm> #include <cmath& ...
- NOIP模拟赛 by hzwer
2015年10月04日NOIP模拟赛 by hzwer (这是小奇=> 小奇挖矿2(mining) [题目背景] 小奇飞船的钻头开启了无限耐久+精准采集模式!这次它要将原矿运到泛光之源的矿 ...
- 小奇模拟赛9.13 by hzwer
2015年9月13日NOIP模拟赛 by hzwer (这是小奇=> 小奇挖矿(explo) [题目背景] 小奇要开采一些矿物,它驾驶着一台带有钻头(初始能力值w)的飞船,按既定路线依次飞 ...
- PKUSC 模拟赛 day1 下午总结
下午到了机房之后又困又饿,还要被强行摁着看英文题,简直差评 第一题是NOIP模拟赛的原题,随便模拟就好啦 本人模拟功力太渣不小心打错了个变量,居然调了40多分钟QAQ #include<cstd ...
- [GRYZ]寒假模拟赛
写在前面 这是首次广饶一中的OIERS自编自导,自出自做(zuo)的模拟赛. 鉴于水平气压比较低,机(wei)智(suo)的WMY/XYD/HYXZC就上网FQ下海找了不少水(fei)题,经过他们优( ...
- BZOJ2741: 【FOTILE模拟赛】L
2741: [FOTILE模拟赛]L Time Limit: 15 Sec Memory Limit: 162 MBSubmit: 1170 Solved: 303[Submit][Status] ...
- 大家AK杯 灰天飞雁NOIP模拟赛题解/数据/标程
数据 http://files.cnblogs.com/htfy/data.zip 简要题解 桌球碰撞 纯模拟,注意一开始就在袋口和v=0的情况.v和坐标可以是小数.为保险起见最好用extended/ ...
随机推荐
- VMware Workstation虚拟机 + 许可证密钥
VMware Workstation虚拟机 + 许可证密钥 VMware Workstation是什么? VMware简介 VMware 安装 VMware系统要求 VMware 版本下载地址 许可证 ...
- MVCC能否解决幻读?
一.什么是MVCC 多版本控制: 指的是一种提高并发的技术.最早的数据库系统,只有读读之间可以并发,读写,写读,写写都要阻塞.引入多版本之后,只有写写之间相互阻塞,其他三种操作都可以并行,这样大幅度提 ...
- vim命令之多行注释
vim常用命令之多行注释和多行删除 vim中多行注释和多行删除命令,这些命令也是经常用到的一些小技巧,可以大大提高工作效率. 1.多行注释: 1. 首先按esc进入命令行模式下,按下Ctrl + v, ...
- vue项目自动导入components
开发项目中一般组件都放在 components 目录下,对于一些高频使用的组件我们需要在入口文件中设置为全局组件, 一个一个搞,很繁琐,这里通过webpack自动挂载components为全局组件. ...
- Angular 18+ 高级教程 – Memory leak, unsubscribe, onDestroy
何谓 Memory Leak? Angular 是 SPA (Single-page application) 框架,用来开发 SPA. SPA 最大的特点就是它不刷新页面,不刷新就容易造成 memo ...
- ASP.NET Core – Case Style Conversion
前言 之前就有写过一篇 <<前后端沟通 naming conversion 转换需要知道的事>> 这篇做一个总结整理. 我们知道 C# 的 Property 是 PascalC ...
- 面试官:GROUP BY和DISTINCT有什么区别?
在 MySQL 中,GROUP BY 和 DISTINCT 都是用来处理查询结果中的重复数据,并且在官方的描述文档中也可以看出:在大多数情况下 DISTINCT 是特殊的 GROUP BY,如下图所示 ...
- Blazor开发框架Known-V2.0.11
Known今天发布了V2.0.11版本,本次版本添加了系统WebApi在线测试,系统菜单样式配置,表格支持用户设置栏位显隐和顺序,系统上下文支持静态组件与后端交互,以及对PgSQL进行了详细的测试,修 ...
- [使用目前最新版]HybridCLR6.9.0+YooAsset2.2.4实现纯C# Unity热更新方案 (一)
1.前言 什么是热更新 游戏或者软件更新时,无需重新下载客户端进行安装,而是在应用程序启动的情况下,在内部进行资源或者代码更新 Unity目前常用热更新解决方案 HybridCLR,Xlua,ILRu ...
- PHP面试,Redis
1. 什么是Redis? Redis(Remote Dictionary Server)是一个开源的内存数据存储系统,它可以用作数据库.缓存和消息中间件.它支持多种数据结构,如字符串.哈希.列表.集合 ...