CF1511G Chips on a Board (倍增)
题面
转化方便版题意:
有
n
n
n 堆石子,第
i
i
i 堆有
c
i
∈
[
1
,
m
]
c_i\in [1,m]
ci∈[1,m] 个石子,有
q
q
q 次询问,每次询问给出
L
i
,
R
i
L_i,R_i
Li,Ri ,先把
c
i
∉
[
L
i
,
R
i
]
c_i\not\in [L_i,R_i]
ci∈[Li,Ri] 的石堆都扔掉,然后把每堆石子减少
L
i
L_i
Li 个,最后用剩下的若干堆石子做
N
i
m
Nim
Nim 游戏,先手必胜输出
A
\tt A
A ,后手必胜输出
B
\tt B
B 。
1
≤
n
,
m
,
q
≤
2
⋅
1
0
5
1\leq n,m,q\leq2\cdot10^5
1≤n,m,q≤2⋅105.
题解
官方题解,是
O
(
N
N
log
N
)
O(N\sqrt{N\log N})
O(NNlogN
) 的做法。
对每个询问暴力求解,是
O
(
N
2
)
O(N^2)
O(N2) 的。或者,如果记录每一种
c
i
c_i
ci 值的出现次数的话,也可以是
O
(
N
M
)
O(NM)
O(NM) 的。后者可以优化:
c
i
c_i
ci 的二进制表示有
18
\tt18
18 位,我们把前面九位和后面九位分开算,这样,分别就只有
2
9
=
512
2^9=512
29=512 种取值,也就是
M
\sqrt{M}
M
种取值了,这就增加了暴力的可能性。同时,只管前九位和后九位都是能比较方便地处理加减法的,因此这样刚好是可行的,要是分成前六位、中六位、后六位就及其不好做了。
但是,处理后九位数字还是比较麻烦的。而且,这个时间复杂度也不优。
不如看看下面又易懂又好写还在时间复杂度上暴踩官解的做法。
真是妙蛙种子吃着妙脆角,妙进了米奇妙妙屋,妙到家了
真的就不能每一位分开来做了吗?
加减法固然会对二进制表示产生不好计量的影响,但是我们有这么一条很容易发现的结论:
- 若
A
<
2
k
A<2^k
A<2k ,则
A
+
2
k
=
A
x
o
r
2
k
A+2^k=A~xor~2^k
A+2k=A xor 2k
这种情况下,加法是等同于异或的!
那我们不妨就想个办法,能不能把减法变成加法,然后把要加的部分按位拆分开来,利用上面的结论一步一步异或进去呢?
有!那就是倍增。倍增可以把减法换成加法,而且不难发现,倍增刚好是从高位往低位考虑的,前面要加的数的 lowbit 一定比后面的数都大。
我们定义
f
[
i
]
[
j
]
f[i][j]
f[i][j] 为询问
L
=
i
,
R
=
i
+
2
j
−
1
L=i,R=i+2^j-1
L=i,R=i+2j−1 时的答案,不难发现
f
[
i
]
[
0
]
=
0
f[i][0]=0
f[i][0]=0。
计算
f
[
i
]
[
j
]
f[i][j]
f[i][j] 的时候,先异或上
f
[
i
]
[
j
−
1
]
f[i][j-1]
f[i][j−1] ,然后由于
f
[
i
+
2
j
−
1
]
[
j
−
1
]
f[i+2^{j-1}][j-1]
f[i+2j−1][j−1] 中的每堆石子个数
<
2
j
−
1
< 2^{j-1}
<2j−1 ,我们把这些石堆加上
2
j
−
1
2^{j-1}
2j−1 时,等价于异或
2
j
−
1
2^{j-1}
2j−1,因此我们只需要再知道
[
i
+
2
j
−
1
,
i
+
2
j
−
1
]
[i+2^{j-1},i+2^j-1]
[i+2j−1,i+2j−1] 区间之内石堆的个数,就可以转移了。令
c
t
[
i
]
[
j
]
ct[i][j]
ct[i][j] 表示
c
i
∈
[
i
,
i
+
2
j
−
1
]
c_i\in[i,i+2^j-1]
ci∈[i,i+2j−1] 的石堆的个数,则:
f
[
i
]
[
j
]
=
f
[
i
]
[
j
−
1
]
x
o
r
f
[
i
+
2
j
−
1
]
[
j
−
1
]
x
o
r
(
2
j
−
1
⋅
(
c
t
[
i
+
2
j
−
1
]
[
j
−
1
]
%
2
)
)
c
t
[
i
]
[
j
]
=
c
t
[
i
]
[
j
−
1
]
+
c
t
[
i
+
2
j
−
1
]
[
j
−
1
]
f[i][j]=f[i][j-1]~{\tt xor}~f[i+2^{j-1}][j-1]~{\tt xor}~\Big( 2^{j-1}\cdot(ct[i+2^{j-1}][j-1]\,\%\,2) \Big)\\ ct[i][j]=ct[i][j-1]+ct[i+2^{j-1}][j-1]
f[i][j]=f[i][j−1] xor f[i+2j−1][j−1] xor (2j−1⋅(ct[i+2j−1][j−1]%2))ct[i][j]=ct[i][j−1]+ct[i+2j−1][j−1]
询问的时候,类似的。由于是倍增,每次访问到的
f
[
i
]
[
j
]
f[i][j]
f[i][j] 的
j
j
j 都会变小,也就是说它所代表的这个区间内的石堆
c
i
c_i
ci 都小于先前的
2
j
2^j
2j ,都可以把加法换成异或,再通过
c
t
[
i
]
[
j
]
ct[i][j]
ct[i][j] 补到
f
[
i
]
[
j
]
f[i][j]
f[i][j] 中。
代码也很好理解,基本是标准的预处理倍增。时间复杂度只有
O
(
N
log
N
)
O(N\log N)
O(NlogN) 。
CODE
比解说还短的倍增代码
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define MAXN 200005
#define ENDL putchar('\n')
#define LL long long
#define DB double
#define lowbit(x) ((-x) & (x))
LL read() {
LL f = 1,x = 0;char s = getchar();
while(s < '0' || s > '9') {if(s=='-')f = -f;s = getchar();}
while(s >= '0' && s <= '9') {x=x*10+(s-'0');s = getchar();}
return f * x;
}
int n,m,i,j,s,o,k;
int c[MAXN],dp[MAXN][20],ct[MAXN][20];
int main() {
// Input
n = read();m = read();
for(int i = 1;i <= n;i ++)
c[i] = read(),ct[c[i]][0] ++;
// Init
for(int i = m;i > 0;i --) {
for(int j = 1;i+(1<<j)-1 <= m;j ++) {
ct[i][j] = ct[i][j-1] + ct[i+(1<<(j-1))][j-1];
dp[i][j] = dp[i][j-1] ^ dp[i+(1<<(j-1))][j-1] ^ ((ct[i+(1<<(j-1))][j-1] & 1) ? (1<<(j-1)):0);
}
}
// Query
int q = read();
while(q --) {
s = read();o = read();
int xr = 0,as = 0;
for(int j = 18;j >= 0;j --) {
if(s+(1<<j)-1 <= o) {
as ^= dp[s][j]^((ct[s][j] & 1) ? xr:0);
xr ^= (1<<j); s += (1<<j);
}
}
printf(as ? "A":"B");
}
return 0;
}
CF1511G Chips on a Board (倍增)的更多相关文章
- Codeforces 1511G - Chips on a Board(01trie/倍增)
Codeforces 题面传送门 & 洛谷题面传送门 一道名副其实的 hot tea 首先显然可以发现这俩人在玩 Nim 游戏,因此对于一个 \(c_i\in[l,r]\) 其 SG 值就是 ...
- Architecture of Device I/O Drivers, Device Driver Design
http://www.kalinskyassociates.com/Wpaper4.html Architecture of Device I/O Drivers Many embedded syst ...
- ARM JTAG 信号 RTCK 应该如何处理?
用户在调试内嵌可综合内核的 CPU 如 ARM7TDMI-S 时,需要通过打开仿真器的自适应时钟功能. 此时,ARM仿真器根据 RTCK 时钟信号的频率,产生可用于 CPU 内核当前时钟主频的最快的 ...
- Implementation of Serial Wire JTAG flash programming in ARM Cortex M3 Processors
Implementation of Serial Wire JTAG flash programming in ARM Cortex M3 Processors The goal of the pro ...
- CF1511G-Chips on a Board【倍增】
正题 题目链接:https://www.luogu.com.cn/problem/CF1511G 题目大意 给出\(n*m\)的棋盘上每一行有一个棋子,双方轮流操作可以把一个棋子向左移动若干步(不能不 ...
- Codeforces Round #194 (Div. 2) D. Chips
D. Chips time limit per test:1 second memory limit per test:256 megabytes input:standard input outpu ...
- ACM-ICPC Beijing 2016 Genius ACM(倍增+二分)
描述 给定一个整数 M,对于任意一个整数集合 S,定义“校验值”如下: 从集合 S 中取出 M 对数(即 2∗M 个数,不能重复使用集合中的数,如果 S 中的整 数不够 M 对,则取到不能取为止),使 ...
- CH0601 Genius ACM【倍增】【归并排序】
0601 Genius ACM 0x00「基本算法」例题 描述 给定一个整数 M,对于任意一个整数集合 S,定义“校验值”如下: 从集合 S 中取出 M 对数(即 2∗M 个数,不能重复使用集合中的数 ...
- Codeforces Round #194 (Div. 1) B. Chips 水题
B. Chips Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/333/problem/B D ...
随机推荐
- 『忘了再学』Shell基础 — 28、AWK中条件表达式说明
目录 1.AWK的条件表达 2.条件表达式说明 (1)BEGIN (2)END (3)关系运算符 (4)说明AWK中条件表达式的执行过程 (5)AWK中使用正则表达式 (6)A~B练习 1.AWK的条 ...
- DS18B20数字温度计 (一) 电气特性, 供电和接线方式
目录 DS18B20数字温度计 (一) 电气特性, 供电和接线方式 DS18B20数字温度计 (二) 测温, ROM和CRC校验 DS18B20数字温度计 (三) 1-WIRE总线ROM搜索算法 DS ...
- 【spring源码系列】之【FactoryBean类型的接口】
1.概述 目前我们知道,spring创建bean有多种方式,比如xml方式创建,比如@Component,@Service,@Controler,@Repository注解创建,比如@Autowire ...
- 使用PowerShell安装MySQL
更新记录 2022年4月16日:本文迁移自Panda666原博客,原发布时间:2021年7月10日. 2022年4月16日:更新MySQL下载链接. 一.说明与准备工作 根据MySQL官网提供的安装M ...
- 解决maven依赖冲突,这篇就够了!
一.前言 什么是依赖冲突 依赖冲突是指项目依赖的某一个jar包,有多个不同的版本,因而造成了包版本冲突. 依赖冲突的原因 我们在maven项目的pom中 一般会引用许许多多的dependency.例如 ...
- 1.2 操作系统的第二个功能——并发功能 -《zobolの操作系统学习札记》
1.2 操作系统的第二个功能--并发功能 目录 1.2 操作系统的第二个功能--并发功能 问1:什么是并发功能?并发功能是必要的吗? 问2:并发功能必须要求拥有多核CPU吗? 问3:多核CPU和单核C ...
- TCP和UDP协议的区别以及原理
参考文章https://blog.csdn.net/weixin_38483133/article/details/123864253
- 如何编写测试团队通用的Jmeter脚本
平时学习.工作过程中,编写的一些jmeter脚本,相信大多数都遇到过这个问题.那就是:如果换一台电脑运行,文件路径不一样,会导致运行失败. 前不久,自己就真真切切遇到过一回,A同学写了个脚本用于压测, ...
- 抢先体验! 在浏览器里写 Flutter 是一种什么体验?
Invertase 是一间位于英国的开源软件制作公司.主要构建关于开发者工具.SDK 等应用程序,早在 Flutter 2.2 的时候,Invertase 团队就开始帮助构建和贡献 Firebase ...
- IDEA 开发工具-插件{[转载]
00 idea 开发工具使用技巧 01 idea插件推荐-- 02 IDEA插件 03 IDEA值得推荐的20款优秀的插件 04 IDEA插件精选」安利一个IDEA骚操作:一键生成方法的序列图