三月了,又是一个新的起点,继续前行。
3.1
说实话今天口胡了一道题,一直在思考,做的题比较少(也比较水)
然后第一次自己打SAM什么的,太弱了qwq。
BZOJ1303——Others——Miscellaneous
将大于中位数的值设为1,小于的设为-1,等于的设为0,则可以制造一个前缀和数组——在数组中只要某两个位置中值相等,则说明存在一段和为0的段,只需要排个序统计下即可。
BZOJ3926——String——SAM
题目的关键点其实就在于只有20个叶子节点。
这样每个叶子节点到根的路径就相当于一个字符串,我们要求的就是这20个字符串不同的字串个数。
用SAM实现即可。
BZOJ1037——DP——Common
用
f[i][j][x][y]
f
[
i
]
[
j
]
[
x
]
[
y
]
表示到第
i
i
个人,总共个男生,以
i
i
结尾的任意长度中男生最多比女生多,女生最多比男生多
y
y
的方案数,然后dp即可。
3.2
今天又一轮互出好题qwq。
然后今天做的题比较多。
但是教练说我应该分出一部分时间来看一些论文之类的东西,研究深入一点。
确实,做了这么多题发现虽然见识面广了,许多见过的类似题目都可以很快出解。但是对于一些新颖的题目往往需要思考很久,甚至简单的问题转化什么的也会掉坑里。
综上,看情况修一修集训队论文。
ZOJ1363——DP——Probability
令表示前
i
i
个桌上个的概率,
nm
n
m
的dp式很简单。
f[i][j]=f[i−1][j+1]∗(j+1)c+f[i−1][j−1]∗(j+1)c
f
[
i
]
[
j
]
=
f
[
i
−
1
]
[
j
+
1
]
∗
(
j
+
1
)
c
+
f
[
i
−
1
]
[
j
−
1
]
∗
(
j
+
1
)
c
但是直接做会TLE,所以这里玄学地缩小了
n
n
的范围,
发现到了后面概率对答案的影响很小,而精度不要求很精确,所以我们直接将n调到6w左右就能过了。
BZOJ2179——Math——FFT
fft裸题,第一次写啊。
BZOJ2893——Map——Network_Flow——Cost_Flow
首先对于有向图我们缩个环,得到一个DAG。
考虑用费用流的特性解决这道题,我们可以这样建边(以下表示流量为
c
c
,费用为):
将每个点
u
u
拆点,对于,建立两条边
(1,1)和(INF,0)
(
1
,
1
)
和
(
I
N
F
,
0
)
,这样可以保证每个点可以经过多次。
对于
S−>u和u′−>T
S
−
>
u
和
u
′
−
>
T
,建边
(INF,0)
(
I
N
F
,
0
)
,对于DAG中的每条边
(u,v)
(
u
,
v
)
,建立边
u′−>v(INF,0)
u
′
−
>
v
(
I
N
F
,
0
)
。
那么最大费用流每次会尽量走费用多的边,即走尽量多的点,正确性由网络流保证,增广的次数就是答案。
BZOJ4052——Math——GCD
以一个位置为结尾的所有连续子序列,不同gcd的数目是log级的
所以直接暴力就可以过了。
BZOJ4481——Math——Probability
利用等比数列公式计算女方选某个人的概率:
(1−p)j−1∗p1−(1−p)m
(
1
−
p
)
j
−
1
∗
p
1
−
(
1
−
p
)
m
这样就可以算出这个位置被选的概率。
这样,之后开始选择的女方如果选了某个更靠前位置,就多了这么些概率贡献一个逆序对。
将边按双关键字排序,用树状数组维护一个类似逆序对的东西即可。数据卡精度qwq。
BZOJ4850——Divide_Conquer——Divide_Block——Common
发现
|i−j|−−−−−√
|
i
−
j
|
的值只有
n−−√
n
种,
将原式移项后发现对答案可能有贡献的只有每个
|i−j|−−−−−√
|
i
−
j
|
下的最大的
hj
h
j
。
因此我们分块后用rmq处理即可。
3.4
从这周开始做题量会下来,因为一方面要看论文补功底,一方面要准备讲课课件。
BZOJ4456——Divide_Conquer——Divide_Conquer——Shortest_Way
之前做过,还写了题解,放在这水。
BZOJ4449——Divide_Conquer——Divide_Conquer——Shortest_Way/——Divide_Conquer——Point_Divide
对于当前的图,找到一条边能够把图分成左右两半。
对于询问
(x,y)
(
x
,
y
)
,若
x
x
在这条边的左边,在这条边的右边,那么这个询问的最短路程一定经过这条边的两个端点之一,用spfa什么的求出这条边两个端点到当前图的每个点的最短路径,然后就可以求出这样跨过这条的询问的答案。然后递归处理左右两半。
另一种点分的方法参考Claris:
首先拓扑,每次取出度数为2的点,这样可以把所有三角形都找到。那么建出对偶图,会发现是一棵树。
对这棵树进行点分治,每次取出重心,DFS求出所有在里面的点,然后从重心3个点分别做一次BFS。
对于每个询问,如果不经过重心这个区域,那么递归求解,否则用BFS的结果回答即可。
BZOJ4518——DP——Parallelogram
经过冷静分析,发现题目要求最小化:
化简后得到:
那么现在知道 m和sum m 和 s u m ,显然是一个斜率优化的形式,而且也有决策单调性,乱搞即可。
3.5
BZOJ2229——Divide_Conquer——Divide_Conquer——Minimal_Cut
首先,注意这样一个事实:如果
(X,Y)
(
X
,
Y
)
是某个
s1−t1
s
1
−
t
1
最小割,
(Z,W)
(
Z
,
W
)
是某个
s2−t2
s
2
−
t
2
最小割,那么
X∩Z
X
∩
Z
、
X∩W
X
∩
W
、
Y∩Z
Y
∩
Z
、
Y∩W
Y
∩
W
这四项不可能均非空。也就是说,最小割不可能相互跨立。
这个蕴含了,最多一共有
N−1
N
−
1
个不同的
s−t
s
−
t
最小割。只需把这些割找出来即可。
以上,我们利用分治,将求
n2
n
2
个最小割变成求
(n−1)
(
n
−
1
)
次最小割。
我们在区间
[l,r]
[
l
,
r
]
中随便找两个点,求出最小割,将与
S
S
一个集合的放到左边,与一个集合的放到右面,然后更新所有点对之间的最小割,再继续分治处理左右两边。
上面的最小割的证明可以参考2016集训队王文涛的论文。
BZOJ4519——Divide_Conquer——Divide_Conquer——Minimal_Cut
和2229是一样的,所以我直接copy过来,直接改了一点就算了。
中间无用的内容都没改,所以跑的很慢233,不过肯定是能过的。
CF103D——Others——Miscellaneous
当
b
b
比较小的时候dp处理,当比较大的时候暴力算
阙值取
n−−√
n
就行了,这样每个询问就可以在
n−−√
n
的时间内得解
但是内存限制有点死233,,所以先离线询问再做。
3.7
周末测试题昨天做完了,开始写分治题,下周五前要做完ppt讲分治。
BZOJ2152——Divide_Conquer——Point_Divide
点分治入门题,没有什么特别的东西要处理,在递归下去的时候计算路径%3后每一种有多少个就行了。
HDU4812——Divide_Conquer——Point_Divide
继续点分的练习,还是老套路,不过我们要先预处理一下逆元,然后用个map来查询就行了。
SPOJ_QTREE4——Divide_Conquery——Edge_Divide
论文题,链分治+线段树+堆或者边分治+堆都可以做,我写了边分,因为比较好写。
题解去看论文吧233。
SPOJ_FTOUR2——Divide_Conquer——Point_Divide
还是论文题,用线段树维护前缀最大值进行dp转移。
这道题TLE了无数次,原因是少写了个if
分治是真的可怕,尤其是论文题调了好久。
3.8
今天差不多把要写的题目都写完了,明天开始就可以做ppt了。
BZOJ1492——Divide_Conquer——CDQ
n2
n
2
dp很显然,设
x[i]
x
[
i
]
,
y[i]
y
[
i
]
分别表示第
i
i
天最多买进的两种金券的数量,那么
考虑斜率优化,我们有
f[i]=max(x[j]∗a[i]+y[j]∗b[i]),y[j]=(−a[i]b[i])∗x[j]+f[i]b[i] f [ i ] = m a x ( x [ j ] ∗ a [ i ] + y [ j ] ∗ b [ i ] ) , y [ j ] = ( − a [ i ] b [ i ] ) ∗ x [ j ] + f [ i ] b [ i ]
−a[i]b[i] − a [ i ] b [ i ] 看作斜率,表示成了关于平面 x,y x , y 上的斜率关系。 bi b i 不变,要让 fi f i 最大,就要让截距最大。很容易发现,满足的点都在 (x,y) ( x , y ) 的上凸壳上,所以我们维护这个凸壳。
由于 xi x i 不一定是连续的,不能直接单调队列做,于是我们可以采用CDQ分治
BZOJ2149——Divide_Conquer——CDQ
这题和下一题都丢在了题解
CF660F——Divide_Conquer——CDQ
看上面。
BZOJ3730——Divide_Conquer——Dynamic_Tree_Divide
考虑动态树分治。我们对于每个点(点分树)维护两个树状数组。两个树状数组都以距离为下标,权值为内容。第一个树状数组维护子树中距离该点为
k
k
的权值和,第二个维护距离该点父亲距离为的权值和。这样改权值时我们暴力爬树高,
log2
l
o
g
2
复杂度。查询的时候一样爬树高,要注意容斥(把当前子树k的先加起来,往祖先上爬,如果距离小于
k
k
,假设为,我们到祖先上去求一个
k−d
k
−
d
,再容斥掉原来这棵子树里被计算过的,这就是第二个树状数组的用处)。
3.15
好久没有写过题目了。
前几天得流感去了医院,今天正式打了一套模拟赛,手感一般般吧,并不能长时间做题了。
分治的练习题今天也是写完了。
BZOJ2001——Divide_Conquer——Divide_Conquer——Common
对于一个询问区间[l,r],如果我们不看这些修改了的边,必然有一些边是一定在MST上的,同时必然有一些边是不可能在MST上的。那么:
首先是删除无用的边,我们对于一个修改区间[l,r],可以把待修改的边设为INF,做一遍MST,这样不在这个MST上的非INF边就可以删去了(显然在原图的情况下这些边更不可能在MST中)。
然后是合并一定要选的边,对于一个修改区间[l,r],将待修改的边设为-INF,做一遍MST,这样在MST 中的非-INF边一定要被保留,道理显然。这样以后,我们可以将这些非-INF边链接的点缩成一个点,以减小问题规模。
这样分治到l==r的时候我们得到的点数和边数都十分少了,这样就可以再做一遍MST得到答案了。
分治一次时间复杂度是O(mlogm),总复杂度大概多一个logn,不好码。
BZOJ3237——Divide_Conquer——CDQ
维护连通性用DSU,缩小问题规模来考虑分治。
然而两边询问互不影响,所以这种情况下的分治多半是暴力做。
思路明确:首先,把左边没有右边有的边建出来,分治左边。还原并查集后把右边没有左边有的边建出来,分治右边。
每次建的边数为这个区间内的集合中的边数,是一个与n无关的量。
复杂度O(qclogc)
下周sc大佬又要去湖南集训了,吾等蒟蒻只能苦苦挣扎。
3.17
BZOJ2555——String——SAM
码农题,明明身体还这么虚我为什么要刚这种题。
如果不是动态的,当然是按照拓扑序更新parent树,动态的话就是每加入一个节点,就将它parent链上所有节点记录的数量+1.
然后这个用LCT来维护就行了。
BZOJ3998——String——SAM
建出SAM,统计每个点往后有多少个串就好了。
求答案时dfs一遍就行了。
3.20
UOJ370——DP——Compression
毕竟比赛题是有题解的,我这里不说了。
原来还可以用贪心结果剪枝的啊- -,我还卡了卡常- -。
3.21
UOJ371——Divide_Conquer——Binary_Search
我们可以二分答案,这样就可以限制每个点可以到的地方。
然后其实是可以用最短路类似的方法来判定,然而dfs一遍就行了。
BZOJ1520——Map——Network_Flow——Cost_Flow——Common
二分图最小权匹配,无脑费用流。
BZOJ1927——Map——Network_Flow——Cost_Flow——Common
费用流,建图类似最小路径覆盖。
LOJ6119——Divide_Conquer——Point_Divide
树上路径问题,大概率是个点分。
对于每个右端点,我们找出极小的左端点使得在这个区间内大儿子不能获利,显然这是满足单调性的。
然后我们设
A
A
为两个端点都在区间内的路径数量,为两个端点都在区间外的路径数量,如果
A>B
A
>
B
,那么左端点就可以往右移。
设
C
C
为两个端点分别在区间内外的答案,我们发现与前面的不等式是等价的。
设
sum
s
u
m
为总路径数
∗2
∗
2
,
f[i]
f
[
i
]
为一个端点为
i
i
的路径数量那么有
状态恢复ing,明天后天练习一下数据结构。
3.22
BZOJ1861——Data_Structure——Balanced_Binary_Tree——Splay
平衡树裸题,注意插入删除的位置。
BZOJ3653——Data_Structure——Persistent——Segment_Tree
分情况讨论一下:
1.
b
b
比高明且
a
a
和谈笑风生,那么
c
c
只需在的子树中取就好了,此时贡献为
siz[p]∗min(dep[p−1],k)
s
i
z
[
p
]
∗
m
i
n
(
d
e
p
[
p
−
1
]
,
k
)
2.
a
a
比高明且
a
a
和谈笑风生,
c
c
在的子树上,考虑到子树问题,想到dfs序,那么问题变为求子树
a
a
区间中深度在中所有点
siz
s
i
z
的和 ,可以用主席树完成,以
dep
d
e
p
为下标建树。
BZOJ3729——Data_Structure——Balanced_Binary_Tree——Splay
基础博弈,对于一颗子树,显然只有到根距离为奇数的点才有用,因为若距离是偶数则可以模仿。
那么答案就是将距离为奇数的点权模m后异或起来。
强制在线的话用splay维护一下就行了。
BZOJ4567——String——Trie
第一种方案显然是不优的,所以不考虑。
显然所有字符串的后缀关系形成一个树状结构。我们把所有字符串逆向插入Trie树中,然后DFS一遍,就可以得出这个后缀关系。
于是问题转化为求一棵树的拓扑序,满足每一个点的编号减去它父亲编号的和最小。
这满足贪心策略,每次走最小的子树,求出DFS序即可。
LOJ6062——Dtata_Structure——Segment_Tree
首先
B
B
的顺序没什么关系,就从小到大排个序,那么中每个元素能匹配的就是
B
B
的一个后缀。
根据霍尔定理,排序后对于每个,如果它最少能匹配
i
i
个元素,则可以完美匹配。
那么用线段树维护一下就行了。
今天写了三种树(四种),明天从SCOI2016开始倒着做怎么样?
3.23
BZOJ4568——Math——Linear_Basis+——Map——LCA
树上路径问题多半是点分治,这句话还是用得上。
对于每次分治我们求出每个点路径上的数的线性基。
至于询问的异或max这东西就用暴力合并两个线性基就行。
当然最近点分写太多,于是选择用倍增LCA来合并。
BZOJ4569——Map——DSU
可以发现约束其实就是一些对应位置相等的限制,我们使用并查集,采用最暴力方法合并,时间复杂度为
O(nm)
O
(
n
m
)
。如果最后一共剩下
cnt
c
n
t
个集合,如果某个集合不包含第一位,那么它肯定有10种取值,否则只有9种。那么答案就是
9∗10cnt−1
9
∗
10
c
n
t
−
1
(当然
n=1
n
=
1
时答案为10)。
这里速度慢主要因为很多限制是重复的,所以我们要考虑减少重复计算本质上相同的限制。
用ST表实现这一过程,
f[i][j]
f
[
i
]
[
j
]
表示
[i,i+2j−1]
[
i
,
i
+
2
j
−
1
]
这一区间的情况。
对于每一个限制,可以拆成两个大的限制,然后逐层向下传递,直到某一层的两个区间处于同一集合,也就说明这次限制之前已经又过了,就不需要再向下处理。
每一层最坏合并n次,一共
logn
l
o
g
n
层,复杂度是
O(nlogn)
O
(
n
l
o
g
n
)
。
BZOJ4570——Others——Miscellaneous
对于一种环境我们可以只拿一个实数
k
k
替换掉二元组,那么第
i
i
只怪兽的权值就为,这可以转化成在一个二维平面内的一个点
(Ai,Bi)
(
A
i
,
B
i
)
以及一条经过这个点并且斜率为
k
k
的直线在轴和
y
y
轴的截距和。
那么显然如果一个点,如果存在一个点
i
i
,其且
Bj<Bi
B
j
<
B
i
,这个点肯定是没用的。也就是说在中个二维平面中就只有上凸壳中的点是有用的。
当
k
k
值不同时,凸壳上的其中一个点对应的妖怪的权值会取到最大值。并且对于每个点,都有一个取到最大值的范围,上下界就是凸壳上与这个点连接的两条边的斜率。对于每个点都对应了一个双钩函数,那么我们可以用均值不等式,再根据
k
k
值可以取到的范围,讨论出这个双钩函数在当前值域的最小值,以满足题目给定的最大值最小这个要求,最后,对于所有的点取一个最小值就是答案了。
怎么这些题都这么神啊qwq。
3.24
BZOJ4571——Data_Structure——Persistent——Segment_Tree
从高位到低位按位贪心,询问每一位能不能填1,实际上就是查询一段区间是否有某个范围的数,可持久化线段树解决。
BZOJ4572——DP——Contour_Line
这道题根本不会- -,只会最暴力的状压,我们求的就是不合法。
然后实际上要用到轮廓线dp,我是看着std打的qwq。
设
f[i][j][S][x][y]
f
[
i
]
[
j
]
[
S
]
[
x
]
[
y
]
表示填到了
(i,j)
(
i
,
j
)
,轮廓线上每个位置作为末尾是否完全匹配第一个串的状态为
S
S
,与第一个串到了
x
x
,与第二个串到了
y
y
的方案数。
3.25
BZOJ2753——Map——MST
对于第一问直接bfs出答案就行了。
首先显然最后的答案是一颗树,考虑MST。
那么对于每一条边我们按终点节点的h从小到大排序,相等的再按边权排序,直接MST就行了。
注意做MST的时候如果当前边的两端有一个节点没有在bfs中被访问过,这条边是没用的。
BZOJ2754——String——AC_Machine
感觉没有什么好的想法qwq,看网上题解都是暴力。
于是用AC自动机暴力水过。
字符集很大只要在自动机每个结点放map即可
把点名串建树,每个名字在树上匹配,对于匹配的每个结点,沿fail指针对能到达的结点暴力统计答案。
BZOJ2756——Map——Network_Flow——Max_Flow——Common
对棋盘进行黑白染色,设黑格个数为,数值和为
sum1
s
u
m
1
,白格个数为
num2
n
u
m
2
,数值和为
sum2
s
u
m
2
,最后都变为
x
x
。
则
x=sum1–sum2num1–num2
x
=
s
u
m
1
–
s
u
m
2
n
u
m
1
–
n
u
m
2
当
num1!=num2
n
u
m
1
!
=
n
u
m
2
时 可以解出
x
x
再用网络流check即可
当时 可以发现 对于一个合法的
x
x
,都是一个合法的解
所以可以二分
x
x
然后用网络流check
3.26
BZOJ1833——DP——Digit
标准的数位dp,不用多说233.
BZOJ1834——Network_Flow——Cost_Flow——Common
第一问是告诉你建图的最大流。
对于第二问,可以从第一问的残量网络上继续建图,对残量网络上的每一条边建一条容量是INF费用是w的边,然后建一个S,从S向1建一条容量为k,费用为0的边,跑最小费用最大流即可。
BZOJ1835——DP——Data_Structure——Segment_Tree
设表示第
i
i
个村建第个基站的最小花费,则有转移式:
f[i][j]=minf[k][j−1]+cost(k,i)+c[i],j−1<=k<=i−1
f
[
i
]
[
j
]
=
m
i
n
f
[
k
]
[
j
−
1
]
+
c
o
s
t
(
k
,
i
)
+
c
[
i
]
,
j
−
1
<=
k
<=
i
−
1
cost(k,i)=∑w[x],k+1<=x<=i−1
c
o
s
t
(
k
,
i
)
=
∑
w
[
x
]
,
k
+
1
<=
x
<=
i
−
1
, 且
x
x
未被覆盖
需要求一个区间最小值,我们尝试用线段树维护每一层的这个值。
枚举
j
j
,考虑每一层。
我们设
st[i],ed[i]
s
t
[
i
]
,
e
d
[
i
]
分别表示在
i
i
左右距离最远的
st[i],ed[i]
s
t
[
i
]
,
e
d
[
i
]
建基站依旧可以覆盖到
i
i
,假设我们已经求完了要求
f[i+1][j]
f
[
i
+
1
]
[
j
]
,考虑那些恰可以被
i
i
覆盖到而不能被覆盖到的,即满足
ed[x]=i
e
d
[
x
]
=
i
的点,将
[1..st[x]−1]
[
1..
s
t
[
x
]
−
1
]
区间内的线段树值都加
w[x]
w
[
x
]
,意为前一个基站
k
k
位于那么点
x
x
因不会被覆盖到需要做出赔偿。
求的时候查询区间
[1..i−1]
[
1..
i
−
1
]
内线段树值的最小即可,其中
st[i],ed[i]
s
t
[
i
]
,
e
d
[
i
]
可以用二分求。
总的时间复杂度为
O(nklogn)
O
(
n
k
l
o
g
n
)
BZOJ2111——Math——Combinatorial
转化一下,发现就是求一个
n
n
个节点的完全小根堆的种数,因为对于每个点,左右子树的大小都是确定的,显然可以递推。
设方案数为,当前求
i
i
个,左子树大小,右子树大小
r
r
,我们有:
然后组合数用Lucas定理求就好了。
这几天的东西今天才补。
然后篮球赛输给了裁判,三四名决赛班上决定素质一波。
3.27
BZOJ3122——Math——BSGS
这个写了题解
BZOJ3123BZOJ3123——Data_Structure——Persistent——Segment_Tree+Map——LCA
其实第一眼看起来就是一个
LCT
L
C
T
之类的东西,后来发现不会维护。
不过一般来说,常见的思路就是求出
dfs
d
f
s
序来,然后每次查询的时候就是在主席树上查询
x+y−lca−fa[lca]
x
+
y
−
l
c
a
−
f
a
[
l
c
a
]
的值就行了。
但是这个题要动态的给森林中加边,还是强制在线的,所以就需要考虑换一种方法来维护这个东西。
首先先
dfs
d
f
s
出每棵树来,然后对于
link
l
i
n
k
操作,可以启发式合并两个主席树。这里我们把主席树维护的dfs序变成维护每个点到根的这条路径。
所以
link
l
i
n
k
的时候假设我们要把
x
x
合到上,那么我们就一遍
dfs
d
f
s
,
x
x
这棵树,边用当前点的lca
的
的
fadeep
数组在
数
组
在
dfs
的时候动态维护就行了。时间复杂度是
的
时
候
动
态
维
护
就
行
了
。
时
间
复
杂
度
是
O(nlog^2n)$的
3.28
BZOJ3124——Map——BFS
这题随便怎么写应该都过吧。。。
第一问就是bfs两次,第二问的话显然最后的答案一定是连续的一段,那么我们求出其中的一条直径,再从直径上的每个点进行dfs,如果对于某个点有两个最长路,那么显然我们要移动一下答案的区间,乱搞。
这个东西你也可以这样写:在第一次bfs(设选择节点1作为根)后,求所有到1距离最远的点的LCA,然后第二次bfs同样求到rt距离最远的点的LCA,再求两个点的距离。
BZOJ3129——Math——Lucas
又是组合数学,不过这题并不难,然而不知道内幕是不可做的qwq。
这题模数应该要不是很多,不然CRT开不下什么的。
首先考虑没有限制。每一个任取,那就是隔板法,得到
ans=Cn−1m−1
a
n
s
=
C
m
−
1
n
−
1
对于
xi>=ai
x
i
>=
a
i
的限制,那么我们可以看做第
i
i
个先放了个,将
m
m
减去后隔板法,就是
Cn−1m+n−1
C
m
+
n
−
1
n
−
1
再考虑
x<=ai
x
<=
a
i
的限制,因为n1,n2<=8,所以是可以容斥的。
接着组合数取模要扩展Lucas,还要CRT合并。还有就是扩展Lucas要预处理阶乘。
BZOJ3130——Map——Network_Flow——Max_Flow——Common
首先,如果最大流方案已知,应该怎样使费用最大?显然我们应该将流量最大的边花费定为P,其余为0。
也就是说,现在要让流量最大的边尽可能小,这个东西满足单调性,所以二分一下跑最大流判定就行了。
注意是实数二分。
BZOJ3131——DP——Digit
首先我们知道,一个坐标
(i,j)
(
i
,
j
)
在变换后的金子数是
g[i]∗g[j]
g
[
i
]
∗
g
[
j
]
,其中
g[x]
g
[
x
]
为
f[]=x
f
[
]
=
x
的个数。
但还是一脸不可做的样子。
打表以后发现,实际上
f[]
f
[
]
只有不到1w个不同的值,于是我们就可以暴力数位dp。
先搜索出所有的乘积,然后离散化,
设
f[i][j][k]
f
[
i
]
[
j
]
[
k
]
表示
i
i
位数,积为(离散后的下标),到当前枚举位是否大于
n
n
,枚举第位数转移即可。
最后优先队列一个个取出来就行了。
BZOJ3527——Math——FFT
FFT背模板ing,随便推一波式子:
Ei=∑j<iqj(j−i)2−∑j>iqj(j−i)2
E
i
=
∑
j
<
i
q
j
(
j
−
i
)
2
−
∑
j
>
i
q
j
(
j
−
i
)
2
Ei=∑i−1j=1qj(j−i)2−∑nj=i+1qj(j−i)2
E
i
=
∑
j
=
1
i
−
1
q
j
(
j
−
i
)
2
−
∑
j
=
i
+
1
n
q
j
(
j
−
i
)
2
设
f[i]=qi,g[i]=1i2
f
[
i
]
=
q
i
,
g
[
i
]
=
1
i
2
,则
Ei=∑i−1j=1f[j]g[i−j]−∑nj=i+1f[j]g[j−i]
E
i
=
∑
j
=
1
i
−
1
f
[
j
]
g
[
i
−
j
]
−
∑
j
=
i
+
1
n
f
[
j
]
g
[
j
−
i
]
第一个式子就是卷积,第二个式子换元后得到卷积形式:
∑n−1−ij=0f[n−1−j]∗g[j−i]
∑
j
=
0
n
−
1
−
i
f
[
n
−
1
−
j
]
∗
g
[
j
−
i
]
3.29
BZOJ3197——DP——Tree/——Map——Network_Flow——Cost_Flow——Common
这题好神啊,于是我们有题解。
BZOJ3198——Math——Inclusion_Exclusion
判断相似用哈希,然后因为元素个数很少,所以可以容斥。
ans=
a
n
s
=
至少
k
k
的对数至少
k+1
k
+
1
的对数
∗C(k+1,k)+
∗
C
(
k
+
1
,
k
)
+
至少
k+2
k
+
2
的对数
∗C(k+2,k)/dots
∗
C
(
k
+
2
,
k
)
/
d
o
t
s
这个哈希写了很久挂掉了,双哈希都能被卡,于是乎看别人blog学习了一波判冲突。
3.30
BZOJ1922——Map——Shortest_Way——Dijkstra
好久没见到签到题了- -。
对于每个点显然有一个理论到达时间和可行进入时间,这两个取max就是实际到达时间。
我们做dij的时候,每取出一个点,就更新它能到达的点的理论进入时间和它所保护的点的可行进入时间,同时将后者的度-1,当度为0时才可以入堆。
BZOJ1923——Math——Gauss
高斯消元一下就没了。
BZOJ1924——DP——About_Map
对于每一行,我们选择一个横天门,向所有同行的横天门连双向边,向其他门连单向边。每一列同理。
对于自由门,直接向周围八个有门的点连单向边。
缩环后在DAG上dp即可,建图十分科学,最多
16n
16
n
条边(自由门堆一起),不会像某些blog上说最多有
n2
n
2
条边。
BZOJ1925——DP——Common
首先这看起来很像个dp,然后我还只想到最后一位是上升或者下降状态什么的。
正解的dp方程很玄学,我们令
f[i][j]
f
[
i
]
[
j
]
表示前
i
i
个数,最后一个数是且现在是上升状态的方案数。
那么对于
f[i][j−1]
f
[
i
]
[
j
−
1
]
中的每种合法情况,交换
j和j−1
j
和
j
−
1
的位置,仍然合法。
接下来我们要知道除去
j
j
后的排列且最后为下降状态的方案数,设其为
g
g
,显然
因此
f[i][j]=f[i][j−1]+g[i−1][j−1]=f[i][j]+f[i−1][i−1−(j−1)+1]=f[i][j]+f[i−1][i−j+1]
f
[
i
]
[
j
]
=
f
[
i
]
[
j
−
1
]
+
g
[
i
−
1
]
[
j
−
1
]
=
f
[
i
]
[
j
]
+
f
[
i
−
1
]
[
i
−
1
−
(
j
−
1
)
+
1
]
=
f
[
i
]
[
j
]
+
f
[
i
−
1
]
[
i
−
j
+
1
]