这里会口胡一些乍一看会做,或者没时间写(或者懒得写)的题目,或者一道题目的其他解法,应该很少更新,不用等了…
【HDU5201】The Monkey King-容斥
测试地址:The Monkey King
题目大意:
m
m
m只猴子分
n
n
n个桃,其中猴王必须分得严格最多数量的桃,问方案数。
做法: 本题需要用到容斥。
哇,我怎么这么菜,连这种容斥水题都看不出来了…
首先显然枚举猴王能得到的桃子数量
i
i
i,要求剩下的猴子得到的桃子数都小于
i
i
i的方案数,直接算不行就容斥,强制某些猴子得到的桃子数大于等于
i
i
i,然后剩下的分配就是经典的隔板法了,因此我们有以下式子:
∑
i
=
1
n
∑
j
=
0
⌊
n
i
⌋
−
1
(
−
1
)
j
C
m
−
1
j
C
n
−
i
j
+
m
−
j
−
2
m
−
j
−
2
\sum_{i=1}^n\sum_{j=0}^{\lfloor\frac{n}{i}\rfloor-1}(-1)^jC_{m-1}^jC_{n-ij+m-j-2}^{m-j-2}
∑i=1n∑j=0⌊in⌋−1(−1)jCm−1jCn−ij+m−j−2m−j−2
暴力计算即可,时间复杂度为调和级数
O
(
n
log
n
)
O(n\log n)
O(nlogn)。
【HDU5773】The All-purpose Zero-贪心+DP
测试地址:The All-purpose Zero
题目大意: 给定一个序列,有若干个
0
0
0,可以把
0
0
0变成任意数字,问此时能得到的最长上升子序列长度。
做法: 本题需要用到贪心+DP。
这题需要注意到一个非常重要的结论:把
0
0
0全部拿上一定是不亏的。因为对于任意一个不拿完
0
0
0的上升子序列,我们都能把某个数字改成对应位置的
0
0
0来表示。因此我们直接默认取走全部的
0
0
0,而对于剩下的序列,因为
0
0
0默认取了,那么跨过若干个
0
0
0时,两个数的差就必须大于等于中间
0
0
0的个数
+
1
+1
+1才能接上,那么我们直接把每个数减去它前面
0
0
0的数量,对这个序列做LIS,然后加上
0
0
0的数量即可,时间复杂度为
O
(
n
log
n
)
O(n\log n)
O(nlogn)。
不过从一般的求LIS的DP上想也是可以的,我们在DP中要维护一个数组
d
(
i
)
d(i)
d(i),表示长为
i
i
i的上升子序列的末尾元素的最小值,不难发现
d
d
d应该是严格递增的。而在遇到一个
0
0
0时,事实上
d
d
d会产生这样的变化:先全部
+
1
+1
+1,再整体右移一位。所以我们以这样的方式也可以得到和上面差不多一样的结论。
【BZOJ2924】Flat Broken Lines(POI1998)-Dilworth定理+DP
测试地址:Flat Broken Lines
题目大意: 题目上有
n
n
n个点,定义一条平直折线为,每一条线段与
x
x
x轴的夹角都在正负
45
45
45度以内的折线,问至少需要画多少条平直折线才能覆盖所有的点。
做法: 本题需要用到Dilworth定理+DP。
考虑一个点,它下一步能画到的区域是一个夹角是直角的四分之一平面,所以我们把整个坐标系转
45
45
45度,这样就可以变成一个二维平面上的最小偏序路径覆盖问题,用TJOI2015-组合数学那道题的做法做即可。
【BZOJ4245】OR-XOR(ONTAK2015)-按位贪心
测试地址:OR-XOR
做法: 本题需要用到按位贪心。
要使得最后或起来的和最小,想到按位贪心,从高到低枚举每一位能不能为
0
0
0,如果能为
0
0
0就为
0
0
0。那么我们怎么判断呢?实际上我们是要把序列分成
m
m
m段,每段中该位的异或和都要为
0
0
0,那么我们可以求出序列的异或前缀和,选取每个当前位为
0
0
0的为右端点,看能不能选够
m
m
m个就好了,要注意的是第
n
n
n个前缀和如果当前位不为
0
0
0则直接判错。
还有一点要注意,当我们选定了一些位要为
0
0
0,我们判断的时候就要同时考虑这些位,只有这些位同时为
0
0
0的点才能选为右端点。于是我们就解决了此题。
【LuoguP3986】斐波那契数列-扩展欧几里得
测试地址:斐波那契数列
做法: 本题需要用到扩展欧几里得。
虽然是道提高难度的题…但是偶然看到发现很有意思就写一下…
不难注意到数列中每一项都可以表示成
a
F
n
+
b
F
n
+
1
aF_n+bF_{n+1}
aFn+bFn+1的形式,其中
F
n
,
F
n
+
1
F_n,F_{n+1}
Fn,Fn+1为斐波那契数列中相邻的两项。所以我们要求的就是有多少对
a
,
b
a,b
a,b,使得
k
k
k可以表示成上面的形式。
斐波那契数列增长很快,所以我们可以直接枚举这相邻的两项(显然是
log
\log
log级别的),然后用扩展欧几里得乱搞求出每种情况下解的数目即可。
【BZOJ5415】归程(NOI2018)-最短路+Kruskal重构树
测试地址:归程
做法: 本题需要用到最短路+Kruskal重构树。
这题在考场上就A了,不想再写一遍了。
每个询问实际上是求,只走高度大于
p
p
p的边,从点
v
v
v所能走到的点中,从点
1
1
1开始的单源最短路值最小的是多少。所以我们用Dijkstra算法算出单源最短路(SPFA已死,勿念)。接下来这个强制在线的询问,就和ONTAK2015-Peak那道题的加强版基本上一样了,用Kruskal重构树即可。
【BZOJ5418】屠龙勇士(NOI2018)-扩展中国剩余定理
测试地址:屠龙勇士
做法: 本题需要用到扩展中国剩余定理。
说得这么厉害,实际上就是合并模线性同余方程的通用方法,直接搬上来就差不多了。注意血量除以攻击力会对攻击次数限制一个下限。
(但是在考场上还是爆成75…为什么啊…)
【LuoguP3960】列队(NOIP2017)-动态开点线段树
测试地址:列队
做法: 本题需要用到动态开点线段树。
我们发现操作过程中,首先最右边一列没有任何规律,因此只能用动态开点线段树或树状数组维护最右边一列的序号。去掉最右一列之后,每一行有两个部分,左边的部分是原来在这一行内,还没有出过列的那些同学,右边的部分是新插入该行的部分。对于左边的部分,由于编号整体有序,因此我们只需要用动态开点线段树维护已经出列的那些同学,就可以在这个部分内定位了。而对于右边的部分,直接用动态开点线段树维护即可。显而易见的是,使用动态开点线段树的次数一定是
O
(
n
)
O(n)
O(n)的,因为每次操作需要:在行内定位,修改行的对应信息,然后在最右一列中定位行,将对应的位置插入行的信息中去,再将它从最右一列的信息中删除。这些操作都是
O
(
log
n
)
O(\log n)
O(logn)的,因此总的时间复杂度就是
O
(
n
log
n
)
O(n\log n)
O(nlogn)。
【BZOJ5017】炸弹(SNOI2017)-线段树优化建图+SCC缩点+拓扑排序
测试地址:炸弹
题目大意: 有
n
(
≤
5
×
1
0
5
)
n(\le 5\times 10^5)
n(≤5×105)个炸弹,每个炸弹有一个坐标
x
i
x_i
xi和一个半径
r
i
r_i
ri,当一个炸弹爆炸时,会同时引爆坐标在
[
x
i
−
r
i
,
x
i
+
r
i
]
[x_i-r_i,x_i+r_i]
[xi−ri,xi+ri]内的所有炸弹,对每个炸弹求,当引爆这个炸弹后有多少个炸弹会爆炸。
做法: 本题需要用到线段树优化建图+SCC缩点+拓扑排序。
直接暴力连会连出
O
(
n
2
)
O(n^2)
O(n2)条边,炸得透透的。这时我们一看,实际上就是每个点向一个特定区间内的点连边,于是我们使用线段树优化建图的思路,多开一棵线段树,线段树中的点从父亲连向儿子,而每个叶子节点向对应的真点。于是从一个点连向一个区间的点就很简单了,直接从真点向线段树中区间对应的
O
(
log
n
)
O(\log n)
O(logn)个点连边即可。于是再使用SCC缩点和拓扑排序就能很轻易地算出答案了,时间复杂度为
O
(
n
log
n
)
O(n\log n)
O(nlogn)。
【BZOJ2296】随机种子-数论+构造
测试地址:随机种子
题目大意: 对一个数
x
(
≤
1
0
6
)
x(\le 10^6)
x(≤106),找到一个
a
n
s
(
≤
1
0
16
)
ans(\le 10^{16})
ans(≤1016)使得
a
n
s
ans
ans的十进制表示中包含
0
,
1
,
2
,
.
.
.
,
9
0,1,2,...,9
0,1,2,...,9并是
x
x
x的倍数。
做法: 本题需要用到数论+构造。
我们发现答案是
16
16
16位的正整数,所以在最高
10
10
10位填
1
,
2
,
3
,
.
.
,
9
,
0
1,2,3,..,9,0
1,2,3,..,9,0,再用剩下六位数把正整数补齐成
x
x
x的倍数即可。注意
x
=
0
x=0
x=0时无解。
【HDU6048】Puzzle-思维
测试地址:Puzzle
题目大意: 通过题目中所给的方法构造一个类似八数码的
n
×
m
n\times m
n×m数码谜题,求这个谜题可不可解。
做法: 本题需要用到思维。
要做出本题,要证(猜)出一个惊为天人的结论:将格子的数字按照从左到右,从上到下的方式写出(
0
0
0不写),如果逆序对的奇偶性和最后的局面相同就可解。(这怎么可能是人能猜得出来的结论啊…)
大概的证明思路是,首先空格向左或向右对排列没有影响,而向上和向下的次数之和一定是偶数(因为空格的起点和终点相同),因此排列的逆序对数的奇偶性不会改变。
证明了这点,再证明出同奇偶性的状态可以互达就行了。根据某种直觉(实际上就是我看不出来),任何局面都可以被移成,只有右下角
2
×
2
2\times 2
2×2的区域没有确定的状态,强行枚举
6
6
6种情况,发现结论成立。
于是我们只需要求出逆序对数即可,而题目中给的构造方法有一定规律,直接用等差数列求和公式等计算即可。
【HDU5114】Collision-思维+数论
测试地址:Collision
题目大意: 两个小球在一个矩形框里移动,一开始速度都是
(
1
,
1
)
(1,1)
(1,1),碰到矩形边框会进行不消耗能量的碰撞,然后按反射定律确定速度方向,问两个小球第一次相互碰撞时所在的位置。
做法: 本题需要用到思维+数论。
首先,因为碰撞点有可能是在两个整坐标之间的中点,所以为了方便起见,我们一开始就将所有坐标乘
2
2
2。
接下来,显然应该将速度正交分解来考虑。对于
x
x
x坐标来说,两个小球
x
x
x坐标相同当且仅当:
x
1
=
x
2
x_1=x_2
x1=x2,或者
(
x
1
+
x
2
+
2
t
)
m
o
d
  
2
x
=
0
(x_1+x_2+2t)\mod 2x=0
(x1+x2+2t)mod2x=0。至于原因,你画一下图就可以看出来了。对于
y
y
y坐标也同理。
于是我们讨论四种情况(因为上述每种条件都有两种情况),其中包含至少一个
x
1
=
x
2
x_1=x_2
x1=x2这种条件的情况比较容易计算,主要是第四种情况,也就是
x
1
≠
x
2
x_1\ne x_2
x1̸=x2而且
y
1
≠
y
2
y_1\ne y_2
y1̸=y2的情况。
上面的
(
x
1
+
x
2
+
2
t
)
m
o
d
  
2
x
=
0
(x_1+x_2+2t)\mod 2x=0
(x1+x2+2t)mod2x=0可以写成
x
1
+
x
2
+
2
t
=
2
x
⋅
k
1
x_1+x_2+2t=2x\cdot k_1
x1+x2+2t=2x⋅k1。
y
y
y的那个也可以列成这样的式子,于是我们就可以以
t
t
t为等量关系,列一个关于
k
1
k_1
k1和
k
2
k_2
k2的不定方程。这样我们用扩展欧几里得求出一组解后,再进行微调得到最小的非负解
t
t
t即可。
【HDU6040】Hints of sd0061-思维+nth_element
测试地址:Hints of sd0061
题目大意: 一个
n
n
n个元素的数列
a
a
a,若干个询问
b
i
b_i
bi,对每个询问求
a
a
a中第
b
i
+
1
b_i+1
bi+1小的数是多少。
b
i
b_i
bi满足,当
b
i
≠
b
j
,
b
i
<
b
k
,
b
j
<
b
k
b_i\ne b_j,b_i<b_k,b_j<b_k
bi̸=bj,bi<bk,bj<bk成立,则
b
i
+
b
j
<
b
k
b_i+b_j<b_k
bi+bj<bk成立。
做法: 本题需要用到思维+nth_element。
如果只有一个询问,显然应该用nth_element,这个算法的思想类似快速排序,不过因为每次数据范围减半,所以该算法在随机情况下是
O
(
n
)
O(n)
O(n)的(题目中的
a
a
a数列也可以近似认为是随机的)。
而因为
b
i
b_i
bi满足题目中所求的性质,我们很快可以发现,将
b
b
b排序后所得的序列的增长速度和斐波那契数列相似。因此,我们只需要从大到小处理询问,每次处理完后,就不再涉及后面无用的区间,这样总的来说是
O
(
n
)
O(n)
O(n)的。
【HDU5821】Ball-思维
测试地址:Ball
题目大意: 有
n
n
n个盒子,每个盒子里最多放一个球,每个球有颜色。现在给出起始和目标的颜色序列,问能不能按照如下的一种操作方式从起始颜色序列得到目标颜色序列:给定
m
m
m个操作,每个操作将区间
[
l
i
,
r
i
]
[l_i,r_i]
[li,ri]内的盒子里的球取出来,再任意地放回这些盒子里去。
做法: 本题需要用到思维。
首先我们知道,如果有解,则一定存在一种操作方式,使得同种颜色的球出现的相对顺序不变(因为如果相对顺序能发生变化,那它一定能不发生变化)。因此我们给目标序列中的每个球标号,再返回去推出起始序列中每个球的标号,于是每次操作我们就只需贪心地对区间内的标号进行排序即可,如果最后能得到所要的排列就说明有解,反之无解。
【HDU5873】Football Game-思维
测试地址:Football Game
题目大意: 有
m
m
m个球队,每两支球队间进行一次且仅一次比赛,获胜的一方积
2
2
2分,输掉的一方不积分,如果平局就两个队伍各积
1
1
1分。现给出每个球队最后的总积分,问这种积分情况有没有可能出现。
做法: 本题需要用到思维。
我们先来看合法的得分情况有什么必要条件。很显然,在
i
i
i支球队之间的所有比赛中,积分的总数是
i
(
i
−
1
)
i(i-1)
i(i−1),那么最后这
i
i
i支球队的总积分显然应该大于等于
i
(
i
−
1
)
i(i-1)
i(i−1)才是合法的。当
i
=
n
i=n
i=n时,就要求总积分等于
n
(
n
−
1
)
n(n-1)
n(n−1)才是合法的。因此我们可以把队伍的总积分排序,然后看最小的
i
i
i个积分之和是不是满足上述条件来判断必要条件是否合法。接着,我们发现,这个必要条件同时也是充分条件,因为在满足上述条件的情况下,分数的分配其实是任意的。这样我们就解决了这一题。
【HDU4803】Poor Warehouse Keeper-贪心
测试地址:Poor Warehouse Keeper
题目大意: 一个屏幕上有两个数字,分别表示物品的总数和总价,有两个按钮,一个按了一下后,物品总数会增加
1
1
1,并且在单价不变的情况下同时更新总价,而屏幕上显示的仅仅是真实总价的整数部分(但总价的实际值仍被保存),而另一个按了一下后,总价的实际值会增加
1
1
1,总数保持不变。对于一组数据的
x
,
y
x,y
x,y,求要从屏幕上显示
1
,
1
1,1
1,1(总价的实际值也为
1
1
1)到屏幕上显示
x
,
y
x,y
x,y最少要按几次按钮。
做法: 本题需要用到贪心。
首先我们发现,按第一个按钮时单价不变,按第二个按钮是单价增加,因此单价是不降的,而目标单价
s
s
s的范围是:
y
x
−
1
≤
s
<
y
+
1
x
−
1
\frac{y}{x-1}\le s<\frac{y+1}{x-1}
x−1y≤s<x−1y+1。接着我们发现,因为
x
≤
10
x\le 10
x≤10,并且只有按第一个按钮一次时总数增加
1
1
1,因此第一个按钮按的次数已经确认是
x
−
1
x-1
x−1了,那么要求总按键数最小就等于求按第二个键的次数最小。我们发现当总数越大时,按第二个键所增加的单价
1
n
u
m
\frac{1}{num}
num1就越小,就越难达到目标的范围,因此我们发现,越早按第二个键越好。而因为单价有上限,所以我们只需枚举总数
n
u
m
num
num,求总数从
n
u
m
num
num到
n
u
m
+
1
num+1
num+1时,第二个键最多能按多少次,这个能很轻易地用式子
O
(
1
)
O(1)
O(1)算出。这样我们就解决了这一题。
【HDU5881】Tea-找规律
测试地址:Tea
题目大意: 有一个茶壶,无法得知里面茶的具体量,只知道在一个区间
[
L
,
R
]
[L,R]
[L,R]中。要往两个杯子中倒茶(可以精确控制),使得两个杯子中茶的量之差的绝对值不超过
1
1
1,茶壶中可以剩下不超过
1
1
1的量的茶(你可以理解为,虽然你不知道茶的具体量,但是你能感觉到还剩下
1
1
1),求倒茶次数的最小值。
做法: 本题需要用到找规律。
详细的策略看这里。
【BZOJ3574】抄卡组(HNOI2014)-字符串哈希
测试地址:抄卡组
做法: 本题需要用到字符串哈希。
看到那诡异的大的数据范围,基本上确定数组都开不下了,所以要开vector…
然后输入貌似异常毒瘤,这也是我决定不写这道题的原因。
首先我们思考,如果所有字符串都不包含通配符,显然只要字符串哈希后,把哈希值排个序两两比对一下即可。
接下来,如果所有字符串都包含通配符,因为通配符可以匹配任何字符串,因此我们只要看,这些字符串的前缀(这里指字符串最前面的通配符之前的部分,后缀类似)和后缀满不满足一些性质就行了。观察发现,我们把字符串按前缀的长度从小到大排序,那么当且仅当前面的前缀是后面前缀的前缀子串时合法,后缀也一样。还是用字符串哈希匹配即可。
最后是部分字符串包含通配符的情况。首先把不含通配符的字符串进行哈希值比对,如果这些字符串内都出现不同就肯定没希望了,否则我们能得到最后所有字符串应该成为的样子,接着对于每个带通配符的字符串,这个字符串被通配符切割成若干段,我们需要在最终字符串中,从前到后依次匹配出这些连续段,能匹配得出来才是合法的。显然从前往后贪心匹配,同样用字符串哈希即可。
于是这个问题就解决了…不过据说还要进行卡时间等玄幻操作,本人实在是肝不动啊…
【LuoguP4932】浏览器(LGR-054)-位运算+思维
测试地址:浏览器
做法: 暴力刚的话,时间复杂度
O
(
n
2
v
)
O(n^2v)
O(n2v),emmmmmm…
我们需要看出一个性质。令
f
(
x
)
f(x)
f(x)为
x
x
x的二进制表示中为
1
1
1的位数,则:
f
(
x
x
o
r
y
)
=
f
(
x
)
+
f
(
y
)
−
2
⋅
f
(
x
a
n
d
y
)
f(x\space xor\space y)=f(x)+f(y)-2\cdot f(x\space and\space y)
f(x xor y)=f(x)+f(y)−2⋅f(x and y)
因为要求的是
f
(
x
x
o
r
y
)
f(x\space xor\space y)
f(x xor y)的奇偶性,所以上面换成关于模
2
2
2的同余式后,我们惊讶地发现:
f
(
x
x
o
r
y
)
≡
f
(
x
)
+
f
(
y
)
f(x\space xor\space y)\equiv f(x)+f(y)
f(x xor y)≡f(x)+f(y)
于是我们只需要处理出
f
(
x
i
)
f(x_i)
f(xi)的奇偶性,令
c
n
t
0
,
c
n
t
1
cnt_0,cnt_1
cnt0,cnt1为
f
(
x
i
)
f(x_i)
f(xi)为偶/奇数的元素数量,那么答案就是
c
n
t
0
⋅
c
n
t
1
cnt_0\cdot cnt_1
cnt0⋅cnt1了。
而
O
(
n
log
v
)
O(n\log v)
O(nlogv)的复杂度还是有风险被卡,注意到一个
32
32
32位的整数可以拆成两个
16
16
16位的整数,因此我们用
O
(
2
16
)
O(2^{16})
O(216)的时间预处理出所有
16
16
16位整数的
f
(
x
)
f(x)
f(x),实际计算时就可以
O
(
1
)
O(1)
O(1)计算了,那么时间复杂度变为
O
(
2
16
+
n
)
O(2^{16}+n)
O(216+n),就不太可能被卡了。
【CF280C】Game on Tree-概率期望
测试地址:Game on Tree
题目大意: 给定一棵有根树,一开始所有点是白色,每次等概率选择一个白色的点并把它和它的子树中的点全部染黑,求期望多少次后整棵树都被染黑。
做法: 本题需要用到概率期望。
由于期望的可加性,显然期望操作次数等于每个点被操作的概率之和。又发现每个点被操作,当且仅当它是它到根的路径上第一个被操作的点,令它到根路径上的点数为
d
d
d,则这个点被操作的概率就是
1
d
\frac{1}{d}
d1。这样我们就解决了这一题,时间复杂度为
O
(
n
)
O(n)
O(n)。