版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!

仓库源文站点原文


title: "题解 - [LOJ 2286] 「WC2017」挑战" categories:


知名毒瘤卡常题. 别去做, 浪费时间

题目链接

<!-- more -->

原始题面

题目背景

你和同学们找了三道题目用来练习.

这次练习的目标是写出能在时间限制里通过尽量大规模数据的代码.

同学们纷纷写出了优秀的代码. 现在, 他们向你发起了挑战, 他们对每个问题都设置了若干个测试数据, 这是他们能通过的最大规模的测试数据. 现在, 他们想看一看你写的代码究竟能超过多少同学的代码, 通过多大规模的测试数据.

本题分为 $3$ 个任务, 每个任务对应一道题和相应的若干个测试点, 你需要对于每个任务, 设计一个能通过尽量多测试点的程序.

题目描述

任务一

给定 $n$ 个 $32$ 位无符号整数, 将它们从小到大排序.

任务二

有 $2n$ 个人在玩 「石头剪刀布」 游戏. 他们排成两排, 每排 $n$ 个人. 每个人在每一局游戏都使用固定策略, 即对于第 $i (i \in 1, 2)$ 排的第 $j (0 \leq j < n)$ 个人, 用一个整数 $a_{ij}$​​ 表示他的策略, 其中 $0$ 表示只出石头, $1$ 表示只出剪刀, $2$ 表示只出布.

现在有 $q$ 个询问, 每个询问给定三个整数 $x,y,l(0\leq x,y<n,1\leq l\leq n-max(x,y))$, 问将第一排的第 $x∼x+l-1$ 个人和第二排的第 $y∼y+l-1$ 个人比赛之后, 第一排有多少个人会赢.

上文中 「比赛」 的意思是, 对于所有整数 $i$ 满足 $0\leq i<l$,让第一排的第 $x+i$ 个人和 第二排的第 $y+i$ 个人进行 「石头剪刀布」 游戏.

任务三

我们称一个合法的括号串为: 只由左括号和右括号构成, 两种括号的数量相等, 且任意一个前缀的左括号数量不少于右括号数量的串. 现在给定一个由 (, )? 构成的串, 问有多少种不同的方案, 使得将每个 ? 都替换成一个括号之后, 该串变成一 个合法的括号串. 两种方案不同, 当且仅当至少有一个位置的 ? 被替换成了不同的括号.

输入输出格式

输入格式

此题提供了模板程序. 选手可以在此基础上编写自己的程序, 模板程序详见下文数据范围与提示.

第一行一个整数 $task_id(1\leq task_id\leq3)$, 表示任务编号. 接下来是每个具体任务的输入内容.

在输入的同一行中, 相邻的两个整数会被一个空格隔开.

对于任务一: 一行, 两个整数 $n,s$ . 令 $a_0=next_integer(s),a_i=next_integer(a_{i-1}),1\leq i<n$, 则 $a_0,a1,…,a{n-1}$ 即为需要排序的 $n$ 个整数.

对于任务二: 第一行两个整数 $n,q$ . 第二行一个仅包含 $0, 1, 2$ 的长度为 $n$ 的字符串, 第 $i$ 个字符所代表的整数表示第一排第 $i$ 个人的策略(即 $a_{1i}$​​). 第三行格式同第二行, 表示第二排各个人的策略.

对于任务三: 第一行一个整数 $n$, 表示给定的串的长度. 第二行一个字符串, 即为给定的串.

输出格式

对于任务 1: 令 $b$ 为已经排好序的数组, 调用 output_arr(b, n * 4) 即可.

对于任务 2: 将每个询问的答案依次存入 $32$ 位无符号整数数组 $b$ 中(即, 存入 $b_0,b1,⋯,b{q-1}$ 中), 然后调用 output_arr(b, q * 4) 即可.

对于任务 3: 输出一个整数, 表示不同的方案数除以 $2^{32}$​​ 得到的余数.

输入输出样例

输入样例 #1

1
100000 2017012501

输出样例 #1

4275990336

输入样例 #2

2
6 6
200100
200211
5 1 3
2 0 1
2 0 3
2 0 2
2 3 4
0 1 3

输出样例 #2

3349208141

输入样例 #3

3
4
(???

输出样例 #3

2

输入样例 #4

3
4
)???

输出样例 #4

0

说明

数据范围与提示

任务编号 分值 测试点编号 数据范围与约定
1 5 1 $n=100000$
1 19 2 $n=10^8$
1 11 3 $n=2\times10^8$
2 7 4 $n=q=1000$
2 23 5 $n=q=300000$
3 9 6 $n=1000$
3 5 7 $n=120000$
3 7 8 $n=225000$
3 14 9 $n=266666$

模板程序

C++模板
<details open> <summary><font color='orange'>Show code</font></summary> {% icodeweb blog lang:cpp loj-2286/templ.cpp %} </details>
C 模板
<details open> <summary><font color='orange'>Show code</font></summary> {% icodeweb blog lang:cpp loj-2286/templ.c %} </details>
Pascal 模板
<details open> <summary><font color='orange'>Show code</font></summary> {% icodeweb blog lang:cpp loj-2286/templ.pas %} </details>

解题思路

任务一

基数排序, 桶要开小些以便卡入 L1 Cache

任务二

直接 $O(nq)$ 暴力, 使用 popcount 指令和循环展开卡常

任务三

$O(n^2)$ DP, 依旧是用循环展开卡常

代码参考

<details open> <summary><font color='orange'>Show code</font></summary> {% icodeweb cpa_cpp title:LibreOJ_2286 LibreOJ/2286/0.cpp %} </details>