CF1176E
n个点,m条边的连通无向图,要求找出至少n/2个点使得其余的点都与这些点中的一个或几个有至少一条边
随便找一个点,求出每个点离源点的距离,分奇偶距离,取较少的那个点的集合就是答案。
BZOJ4827
注意fft的初始化问题(一些变量的类型为double而不是int)
CF1169E
给出一个长为n(3e5)的序列a[],q(3e5)组询问,每次给出(x,y),问x是否能到达y。
“到达”的定义是存在
x
≤
p
1
<
.
.
<
p
k
≤
y
x\le p_1 < .. < p_k \le y
x≤p1<..<pk≤y 使得
a
p
i
&
a
p
i
+
1
>
0
a_{p_i} \& a_{p_{i+1}}>0
api&api+1>0
从后往前扫描。
令
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j]表示考虑到第 i 个数之后,第 j 位(二进制)为 1 的最靠左的数(即能到达)
令
l
s
t
[
i
]
lst[i]
lst[i]表示当前所扫描的数之后,第 j 位(二进制)为 1 的最靠前的位置
则如果a[i]的第 j 位(二进制)为1 显然
d
p
[
i
]
[
j
]
=
i
dp[i][j]=i
dp[i][j]=i
枚举其它的二进制位 k,用
d
p
[
l
s
t
[
j
]
]
[
k
]
dp[lst[j]][k]
dp[lst[j]][k] 更新
d
p
[
i
]
[
k
]
dp[i][k]
dp[i][k]
查询的时候如果对于
a
[
y
]
a[y]
a[y] 的第
j
j
j 位为1,且
d
p
[
x
]
[
i
]
≤
y
dp[x][i] \le y
dp[x][i]≤y这样 x 必能到达 y 前面的某个位置,也必能到达 y
BZOJ2762
有一些不等式,每次操作添加、删除不等式,查询当x=k时有多少个不等式符合条件。操作数1e5,值域1e6
对值域建树状数组,每次按a分类讨论一下。
当
x
≥
k
x\ge k
x≥k的时候add(k,1);当
x
≤
k
x \le k
x≤k时 add(1,1) add(k+1,-1)
用前缀和代表
i
i
i之前有多少个
≥
\ge
≥,这样一定满足不等式条件。关于负值域,都加一个大数(>1e6)就行
UOJ268
两个链相交当且仅当一个链的lca在另一个链的路径上
ZROJ88
求区间中每一个数都
≥
B
\ge B
≥B的极大区间个数,单点修改,
Q
,
n
≤
1
e
5
;
a
i
≤
1
e
9
Q,n \le 1e5; a_i\le 1e9
Q,n≤1e5;ai≤1e9
用树状数组记录权值,离散化后转化为求
a
i
≥
B
a_i \ge B
ai≥B的个数减去
c
i
≥
B
c_i \ge B
ci≥B的个数,其中
c
i
=
m
i
n
(
a
i
+
1
,
a
i
)
c_i=min(a_{i+1},a_i)
ci=min(ai+1,ai),感觉这个转化还是很妙的
然后开两个树状数组即可
二轮集训Day6T2
一道现场AC的题 qwq
orz hyw
给你一颗n个点的树,有 m 个虫洞,一个人在u结点想到v结点,但他不能经过u到v路径上的任意边(只能走别的边+虫洞)且虫洞至多通过一次,问方案数。虫洞带修改(加、删一个虫洞)
求出dfs序和一个点的子树大小,然后发现一个虫洞左右两个点可以作为两个点扔进坐标系内,横纵坐标就是dfn[x]和lstdfn[x](lstdfn就是子树中dfs最大结点的dfs序),发现问题转化成了动态二维数点问题,套一个cdq分治+树状数组即可,细节很烦,我大概写+调了4h
有一个细节(反例):当x和y属于同一棵子树中,上述方法就萎了,正确解决方法为不妨设x为深度小的点,将x到root,root到其它树拆成两个矩形即可
代码:https://paste.ubuntu.com/p/Nd8hcNpRjb/
ZROJ106
当dp状态几维很大但之间的差很小时,可以只存一维和其它的差
agc001B
去掉前两次反射发现成了平行四边形,可以辗转相减,用取模优化
agc001C
遇到树的直径可以考虑中间点,本题即是
考虑直径的中间点 m i d mid mid,若直径 d d d为偶数,则要求 d i s ( u , m i d ) > d / 2 dis(u,mid)>d/2 dis(u,mid)>d/2,若为奇数,则考虑一条边 ( u , v ) ∈ E (u,v) \in E (u,v)∈E要求 d i s ( u , m i d ) > ( d − 1 ) / 2 & d i s ( v , m i d ) > ( d − 1 ) / 2 dis(u,mid)>(d-1)/2 \ \&\ dis(v,mid)>(d-1)/2 dis(u,mid)>(d−1)/2 & dis(v,mid)>(d−1)/2, O ( n 2 ) O(n^2) O(n2)检验即可
agc001D
遇到要求回文串/有连续一串相同的字符串题目的时候可以考虑建图,本题即是
from editorial:回文串可以认为是两个点连一条边(意义是两端的点相同),只需要看是否连通即可,考虑构造。
引理:若有
>
2
> 2
>2个
a
[
i
]
a[i]
a[i]为奇数,则必无解。
证明:反证法,假设有解,设有
k
k
k个
a
[
i
]
a[i]
a[i]为奇数,则有
(
n
−
k
)
/
2
(n-k)/2
(n−k)/2条绿色边(中间的那个点没有边,即上图的上半部分),同理设
l
l
l个
b
[
i
]
b[i]
b[i]为奇数,有
(
n
−
l
)
/
2
(n-l)/2
(n−l)/2条绿色边,要使图连通,则至少有
n
−
1
n-1
n−1条边,即
(
n
−
k
)
/
2
+
(
n
−
l
)
/
2
≥
n
−
1
(n-k)/2+(n-l)/2 \ge n-1
(n−k)/2+(n−l)/2≥n−1 故
k
+
l
≤
2
k+l \le 2
k+l≤2,而因为
k
>
2
k > 2
k>2,矛盾,故原结论成立
构造:
提前将奇数
a
a
a换到最前最后
若有0个奇数
a
a
a,则可以
1
a
[
1
]
.
.
a
[
m
−
1
]
2
2
.
.
2
1
2
.
.
2
2
1 \ a[1] .. a[m-1] \ 2\ 2 \ .. \ 2 \ 1 \ 2 \ .. \ 2\ 2
1 a[1]..a[m−1] 2 2 .. 2 1 2 .. 2 2
若有1个奇数
a
a
a,则可以
2
2
.
.
2
a
[
2
]
.
.
a
[
m
]
1
2 \ 2 \ ..\ 2\ a[2] \ ..\ a[m] \ 1
2 2 .. 2 a[2] .. a[m] 1
若有2个奇数
a
a
a,则可以
a
[
1
]
+
1
a
[
2
]
.
.
a
[
m
]
2
2
.
.
2
2
a[1]+1 \ a[2] \ ..\ a[m]\ 2 \ 2 \ .. \ 2 \ 2
a[1]+1 a[2] .. a[m] 2 2 .. 2 2
agc001E
一个套路:
C
(
p
−
x
+
q
−
y
,
p
−
x
)
C(p-x+q-y,p-x)
C(p−x+q−y,p−x)为
(
x
,
y
)
−
−
(
p
,
q
)
(x,y) -- (p,q)
(x,y)−−(p,q)的路线的方案数(走右或上)
容斥后即为
(
−
a
[
i
]
,
−
b
[
i
]
)
−
−
(
a
[
j
]
,
b
[
j
]
)
(-a[i],-b[i]) -- (a[j],b[j])
(−a[i],−b[i])−−(a[j],b[j])的方案数减去
C
(
(
a
[
i
]
+
b
[
i
]
)
∗
2
,
a
[
i
]
+
b
[
i
]
)
C((a[i]+b[i])*2,a[i]+b[i])
C((a[i]+b[i])∗2,a[i]+b[i])
然后
O
(
n
2
)
O(n^2)
O(n2)dp+容斥一下就行了
agc001F
一个套路: A [ p [ i ] ] = i A[p[i]]=i A[p[i]]=i然后 ∣ P i − P j ∣ = = 1 |P_i-P_j|==1 ∣Pi−Pj∣==1就变成了 A i A_i Ai 要相邻, A i + 1 . . A i + k − A i A_{i+1}..A_{i+k} - A_i Ai+1..Ai+k−Ai连边, A i − k + 1 . . A i − 1 − A i A_{i-k+1}..A_{i-1} - A_i Ai−k+1..Ai−1−Ai连边,发现边数为 O ( n 2 ) O(n^2) O(n2),再发现只需要连最小值,可以线段树维护,最后拓扑排序一下即可
BZOJ1969
显然答案要求图中(x,y)路径上割边的个数,结论:割边数=边双-1(边双就是不存在桥的连通子图)
考虑用LCT维护边双,利用时光倒流将删边变成加边,用并查集维护每个点,若对于一条边
(
u
,
v
)
(u,v)
(u,v)以前曾出现过,那么说明该子图无桥,缩成一个点,答案就是根节点的size(边双个数)-1,根节点就是 y 的并查集祖先makeroot之后的点
没有重复元素的LCS可以转化为LIS,
O
(
n
2
)
→
O
(
n
l
o
g
n
)
O(n^2) \rightarrow O(nlogn)
O(n2)→O(nlogn)
具体做法:首先将两序列中只出现了一次的数去掉,离散化之后就成了两个排列求LCS且无重复元素
求出a中的每个元素
a
[
i
]
a[i]
a[i]在b中出现的位置
c
[
i
]
c[i]
c[i],求
c
[
i
]
c[i]
c[i]的LIS即可
BZOJ4758
注意到逆序一个子序列相当于将该子序列相邻的元素做若干次交换,令
d
p
[
i
]
[
j
]
[
k
]
[
l
]
dp[i][j][k][l]
dp[i][j][k][l]表示考虑到
a
[
i
.
.
j
]
a[i..j]
a[i..j]值域为
[
k
.
.
l
]
[k..l]
[k..l]的最长不下降子序列长度,转移分为两种
d
p
[
i
]
[
j
]
[
k
]
[
l
]
=
m
a
x
{
d
p
[
i
]
[
j
]
[
k
+
1
]
[
l
]
,
d
p
[
i
]
[
j
]
[
k
]
[
l
−
1
]
}
dp[i][j][k][l]=max\{dp[i][j][k+1][l],dp[i][j][k][l-1]\}
dp[i][j][k][l]=max{dp[i][j][k+1][l],dp[i][j][k][l−1]} 和
d
p
[
i
]
[
j
]
[
k
]
[
l
]
=
m
a
x
{
d
p
[
i
+
1
]
[
j
]
[
k
]
[
l
]
+
(
a
[
i
]
=
=
k
)
,
d
p
[
i
]
[
j
−
1
]
[
k
]
[
l
]
+
(
a
[
j
]
=
=
l
)
}
dp[i][j][k][l]=max\{dp[i+1][j][k][l]+(a[i]==k),dp[i][j-1][k][l]+(a[j]==l)\}
dp[i][j][k][l]=max{dp[i+1][j][k][l]+(a[i]==k),dp[i][j−1][k][l]+(a[j]==l)},这两个转移相当于基本的求LIS的转移,另一个是
d
p
[
i
]
[
j
]
[
k
]
[
l
]
=
m
a
x
{
d
p
[
i
+
1
]
[
j
−
1
]
[
k
]
[
l
]
+
(
a
[
i
]
=
=
l
)
+
(
a
[
j
]
=
=
k
)
}
dp[i][j][k][l]=max\{dp[i+1][j-1][k][l]+(a[i]==l)+(a[j]==k)\}
dp[i][j][k][l]=max{dp[i+1][j−1][k][l]+(a[i]==l)+(a[j]==k)},表示交换
a
[
i
]
、
a
[
j
]
a[i] 、a[j]
a[i]、a[j]后求LIS
POJ3613
最短路,要求路径点数为给定的N,可以使用floyd倍增算法。
将图离散化之后跑矩阵快速幂,发现floyd转移方程可以拆成这样:
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
for(int k=1;k<=n;k++)
c.a[i][j]=min(c.a[i][j],a.a[i][k]+b.a[k][j]);
代表转移一次(多经过一个点)
这样快速幂 N-1 次就是答案
Luogu1273
对树形背包有了更深的理解
一开始我的转移方程为
d
p
[
i
]
[
j
]
=
m
i
n
u
∈
s
o
n
[
i
]
(
d
p
[
u
]
[
s
i
]
)
(
∑
i
=
1
k
s
i
=
j
)
,
k
dp[i][j]=min_{u \in son[i]}(dp[u][s_i]) (\sum_{i=1}^ks_i=j),k
dp[i][j]=minu∈son[i](dp[u][si])(∑i=1ksi=j),k为u的儿子结点个数,这显然过不去
然后有个比较233的做法
for(int j=st;j>=1;j--){
for(int k=1;k<=subt;k++){
if(j-k<0)continue;
dp[x][j]=max(dp[x][j],dp[x][j-k]+dp[u][k]-ed[i].v);
}
}
显然这是做了个树形背包,经过一番思考,也能达到一样的效果
HDU5269
遇到与位有关的题目可以考虑trie
显然lowbit是第一个不相同的二进制位,考虑将位翻转,每次乘上另一边树的大小,这样就求出了有序的答案,无序答案乘以2即可,本题
2^j*num[tr[u][bs^1]
这样写会爆longlong
Stirling数化下降幂:
x
k
=
∑
i
=
0
k
∗
C
(
x
,
i
)
∗
i
!
∗
S
(
k
,
i
)
x^k=\sum_{i=0}^k * C(x,i) * i! * S(k,i)
xk=i=0∑k∗C(x,i)∗i!∗S(k,i)
其中
S
(
k
,
i
)
S(k,i)
S(k,i)表示第二类stirling数,表示将k个不同元素拆到i个集合的方案数
证明考虑左边是不同的集合,右边是枚举(相同的)集合的个数,然后乘一个
i
!
i!
i!变成不同的集合
Stirling数降次例题:ZROJ607
求
∑
j
=
1
i
F
(
j
,
i
)
\sum_{j=1}^{i} F(j, i)
j=1∑iF(j,i)
其中
F
(
l
,
r
)
F(l,r)
F(l,r)为
l
l
l到
r
r
r内所有数字之和的
k
k
k次方,T组询问
n
≤
1
0
5
;
k
≤
100
;
T
≤
5
n \le 10^5; k\le 100; T\le 5
n≤105;k≤100;T≤5
利用Stirling数降幂:
x
k
=
∑
i
=
0
k
∗
C
(
x
,
i
)
∗
i
!
∗
S
(
k
,
i
)
x^k=\sum_{i=0}^k * C(x,i) * i! * S(k,i)
xk=i=0∑k∗C(x,i)∗i!∗S(k,i)
考虑新加一个数
a
a
a,则:
(
x
+
a
)
k
=
∑
i
=
0
k
∗
C
(
x
+
a
,
i
)
∗
i
!
∗
S
(
k
,
i
)
(x+a)^k=\sum_{i=0}^k * C(x+a,i) * i! * S(k,i)
(x+a)k=i=0∑k∗C(x+a,i)∗i!∗S(k,i)
显然只有组合数一项变了,而
C
(
x
,
i
)
=
C
(
x
−
1
,
i
)
+
C
(
x
−
1
,
i
−
1
)
C(x,i)=C(x-1,i)+C(x-1,i-1)
C(x,i)=C(x−1,i)+C(x−1,i−1),所以我们直接考虑每次加一个组合数:
C
(
x
,
i
)
+
C
(
x
,
i
−
1
)
=
C
(
x
+
1
,
i
)
C(x,i) + C(x,i-1) = C(x+1,i)
C(x,i)+C(x,i−1)=C(x+1,i)
⋯
\cdots
⋯
C
(
x
+
a
−
1
,
i
)
+
C
(
x
+
a
−
1
,
i
−
1
)
=
C
(
x
+
a
,
i
)
C(x+a-1,i)+C(x+a-1,i-1)=C(x+a,i)
C(x+a−1,i)+C(x+a−1,i−1)=C(x+a,i)
每次维护一下前缀和即可
qbxtD1T2
求一个大数的最大质因数
考场写了个pollard rho获得了80分的好成绩,剩下两个点因为复杂度不太对T了
O
(
n
1
/
4
∗
T
)
;
n
=
1
e
9
,
T
=
1
e
5
O(n^{1/4}*T); \ \ \ n=1e9, T=1e5
O(n1/4∗T); n=1e9,T=1e5 被卡了
我才不会告诉你是因为我srand(19260817)
然后有一个非常233的做法
考虑筛出
1
e
5
1e5
1e5以内的质数当做素因子(根号n级别),然后每次暴力判断即可
有一个trick:每次遍历的时候不是
1..
n
1..\sqrt n
1..n,而是直接枚举
1..
n
1..\sqrt n
1..n所有质数,众所周知质数密度
1
l
o
g
n
\frac{1}{log \ n}
log n1,然后发现复杂度就喜闻乐见的少了个log,就可以过了
ZROJ999 经典套路
小S有
n
n
n个盒子,每个盒子里都装着若干个玩具。玩具一共有
m
m
m种不同的类型。
现在,小S想要知道有多少种不同的挑选盒子的方式,使得每种种类的玩具都至少在这些盒子里出现了一次。
问题可以转化为:
给一些二进制数,问有多少种选数的方案,满足这些数or起来为1
考虑
g
[
S
]
g[S]
g[S] 为有多少个盒子的玩具集合为
S
S
S
这里面有个经典套路:
容斥一下,转化为
G
[
S
]
G[S]
G[S]为有多少个盒子的玩具集合为
S
S
S及其子集,考虑
f
[
S
]
f[S]
f[S]表示并集为
S
S
S的方案,一样的
F
[
S
]
F[S]
F[S]表示并集为
S
S
S及其子集的方案
然后我们发现
F
[
S
]
=
2
G
[
S
]
F[S] = 2^{G[S]}
F[S]=2G[S]因为我们考虑 S及其子集中的元素有两种选法
然后我们需要容斥回去 F[S] -= F[S^(1<<i)]
这样递推,显然就是
F
→
f
F \rightarrow f
F→f
ZROJ957 调整法
懒得再写一遍了QAQ
考虑调整法:
先求出字典序最小的匹配,然后从后到前考虑
显然满足条件 当且仅当 两种字符交界处的2个字符至少有一个被覆盖
因为字典序最小,所以只需要考虑前面的字符向后即可
如果只能向前考虑,则违反了字典序最小,一定无解。
BZOJ4383 线段树优化建图
本质:当要连一段区间的边时,不妨建一个超级源点,线段树连超级源点,然后超级源点连线段的起始端点(这样的话就能在 log 的复杂度内连 O(n) 条边)
ZROJ987
树链剖分求lca过程中dfs序要放在第二个dfs中
BZOJ 4987
有一颗树,找出K个点A1,A2,…,Ak,使得∑dis(Ai,Ai+1),(1<=i<=K-1)最小
显然这些点最优情况下是一课树,要想让和最小,一个贪心的想法是将和最大的那几条边按在直径上,这样就只被算一次(其它的边算了两次)
令
d
p
[
x
]
[
y
]
[
0
/
1
/
2
]
dp[x][y][0/1/2]
dp[x][y][0/1/2] 表示点
x
x
x 的子树,选了
y
y
y 个点,有
0
/
1
/
2
0/1/2
0/1/2 个直径端点的长度之和最小值
然后转移很神奇,依照树形背包的转移方式
枚举当前子树内有几个直径端点,如果在直径上就算一次,否则算两次
CF403C
题意:
给一个矩阵
A
A
A满足
A
[
i
]
[
j
]
≥
0
A[i][j] \ge 0
A[i][j]≥0 且
∑
A
[
i
]
[
i
]
>
0
\sum A[i][i] > 0
∑A[i][i]>0问是否存在一个k为正整数满足
A
k
A^k
Ak的每个元素都为正
矩阵的
k
k
k次方的图论意义是:
A
[
i
]
[
j
]
A[i][j]
A[i][j]表示
i
,
j
i,j
i,j间是否有边
A
[
i
]
[
j
]
k
A[i][j]^k
A[i][j]k表示
i
,
j
i,j
i,j间是否有一条长度恰好为
k
k
k的路径
然后题目就转化成了:给你一个邻接矩阵,问是否存在两两之间距离恰好为
k
k
k的长度
k
k
k
因为
k
k
k没有限制,所以只需要令
k
k
k为一个比较大的数,然后再看是否有环就行了(因为可以无限加长度)
然后因为
∑
A
[
i
]
[
i
]
>
0
\sum A[i][i] > 0
∑A[i][i]>0,所以肯定有一个自环,这样我们只需要判连通就好了
注意
A
[
]
[
]
A[][]
A[][]中的路径都是单向的,所以需要判两次连通(正反各判一次)
CF407C 题意:
注意到
k
k
k很小,考虑
k
k
k阶差分,注意到
C
(
n
,
m
)
−
C
(
n
−
1
,
m
−
1
)
=
C
(
n
−
1
,
m
)
C(n,m)-C(n-1,m-1)=C(n-1,m)
C(n,m)−C(n−1,m−1)=C(n−1,m),但是直接差分会导致
[
l
,
r
]
[l,r]
[l,r]后面的部分多算,所以就
[
l
,
r
]
[l,r]
[l,r]+C(r-l,0)
[
l
,
r
−
1
]
[l,r-1]
[l,r−1]+C(r-l-1,1) … 就行了
BZOJ4557
树形dp 好题
f
[
i
]
[
j
]
f[i][j]
f[i][j] 表示以 i 为根的子树已经全部覆盖,向上覆盖至少 j 的最小代价
g
[
i
]
[
j
]
g[i][j]
g[i][j] 表示以 i 为根的子树之下还需覆盖至多 j 层(加上 i 共 j 层)的最小代价,就是当前子树需要兄弟节点帮忙覆盖的层数
注意:为什么要多统计个
g
[
]
[
]
g[][]
g[][]呢?因为注意到如果一个点的儿子的覆盖距离为2,则另一个儿子也会被覆盖到,所以
g
[
]
[
]
g[][]
g[][]就统计当前转移的结点至多能被覆盖到哪一层
因为可能出现覆盖
j
j
j比覆盖
j
−
1
j-1
j−1更优的情况,所以
f
[
]
[
]
f[][]
f[][]要求一个后缀min,
g
[
]
[
]
g[][]
g[][]求一个前缀min,答案就是
f
[
1
]
[
0
]
f[1][0]
f[1][0](因为已经后缀min了所以不影响)
Luogu1272
树形dp,设
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j]表示以 i 为 根,当前已经切割出大小为
j
j
j的块的最少次数,设
u
u
u为当前
x
x
x的儿子(需要被转移)
d
p
[
x
]
[
j
]
=
m
i
n
{
d
p
[
x
]
[
j
−
k
]
+
d
p
[
u
]
[
k
]
−
2
}
dp[x][j] = min\{ dp[x][j-k]+dp[u][k]-2 \}
dp[x][j]=min{dp[x][j−k]+dp[u][k]−2}
为什么要减2?因为考虑u这个子树前的
d
p
[
x
]
[
j
−
k
]
dp[x][j-k]
dp[x][j−k]是切割了u一次的,同理
u
u
u在被转移前也与
x
x
x切割了一次,但是其实转移后一次都不需要被切割,所以需要-2
BZOJ2839
二项式反演
一个有N个元素的集合有
2
N
个不同子集(包含空集)
2^{N个不同子集(包含空集)}
2N个不同子集(包含空集),现在要在这
2
N
2^N
2N个集合中取出若干集合(至少一个),使得
它们的交集的元素个数为K,求取法的方案数
设
f
[
K
]
f[K]
f[K]表示交集大小
≥
K
\ge K
≥K的方案数,则
f
[
K
]
=
C
(
n
,
k
)
∗
(
2
2
n
−
i
−
1
)
f[K] = C(n,k)*(2^{2^{n-i}}-1)
f[K]=C(n,k)∗(22n−i−1) (考虑钦定 k 个,剩下的随便选,有
2
n
−
i
2^{n-i}
2n−i个集合,共
2
2
n
−
i
2^{2^{n-i}}
22n−i种 且不能不选)
设
g
[
K
]
g[K]
g[K]表示交集恰好为
K
K
K的方案数,则
f
[
K
]
=
∑
i
=
K
n
C
(
n
,
i
)
g
[
i
]
f[K]=\sum_{i=K}^nC(n,i)g[i]
f[K]=∑i=KnC(n,i)g[i]
根据二项式反演,
g
[
K
]
=
∑
i
=
k
n
(
−
1
)
i
−
k
C
i
k
f
(
i
)
g[K] = \sum_{i=k}^n(-1)^{i-k}C_i^kf(i)
g[K]=∑i=kn(−1)i−kCikf(i)
然后
2
2
X
2^{2^X}
22X用费马小定理,等于
2
(
2
x
)
%
(
m
o
d
−
1
)
2^{(2^x) \% (mod-1)}
2(2x)%(mod−1)两次快速幂即可
ZROJ966
显然
a
n
s
=
∑
i
=
m
n
(
i
−
1
m
−
1
)
∗
(
c
−
1
)
i
−
m
∗
c
n
−
i
ans=\sum_{i=m}^n\binom{i-1}{m-1}*(c-1)^{i-m}*c^{n-i}
ans=i=m∑n(m−1i−1)∗(c−1)i−m∗cn−i
即枚举第i位匹配完成,在前i-1个位中选m-1个匹配数字,剩下i-m位强行失配,即
(
c
−
1
)
i
−
m
(c-1)^{i-m}
(c−1)i−m,剩下n-i位随便选,即
c
n
−
i
c^{n-i}
cn−i
考虑优化,发现容斥一下就变成了求失配的有多少种方案,考虑匹配到0 1 2 3 … m-1 位,即
(
n
i
)
1
i
\binom{n}{i}1^i
(in)1i,然后剩下n-i位强行失配,所以有
(
c
−
1
)
n
−
i
(c-1)^{n-i}
(c−1)n−i,注意不是c而是c-1因为必须钦定失配,所以答案就是
a
n
s
=
∑
i
=
0
m
−
1
(
n
i
)
(
c
−
1
)
n
−
i
ans=\sum_{i=0}^{m-1}\binom{n}{i}(c-1)^{n-i}
ans=i=0∑m−1(in)(c−1)n−i注意到n很大不能直接预处理,所以根据组合数展开形式递推即可
noi.ac 713
分治优化dp
一个显然的
O
(
n
m
2
)
O(nm^2)
O(nm2)的dp是设
p
r
e
[
i
]
[
j
]
pre[i][j]
pre[i][j]表示[1…i]模m为j的那个价值式子的和,
s
u
f
[
i
]
[
j
]
suf[i][j]
suf[i][j]表示[i…n] …
然后对于每一个i,设f[j]表示模m为j的价值式子的和,则
f
[
(
j
+
k
)
m
o
d
m
]
=
m
i
n
{
p
r
e
[
i
−
1
]
[
j
]
+
s
u
f
[
i
+
1
]
[
k
]
}
f[(j+k) \mod m]=min\{pre[i-1][j]+suf[i+1][k]\}
f[(j+k)modm]=min{pre[i−1][j]+suf[i+1][k]}
然后我们考虑用分治优化dp,当我们
s
o
l
v
e
(
l
,
r
)
solve(l,r)
solve(l,r)时就表示当前不选
[
l
,
r
]
[l,r]
[l,r]的式子的和,显然对于每一个
[
l
,
l
]
[l,l]
[l,l],当前的dp值就是那个式子在
i
=
l
i=l
i=l的答案
然后大概可以这么写(g为辅助数组,add(w,v)为给所有的i,(w+i)%m的位置加上v):
(solve(l,mid)的时候加上了
[
m
i
d
+
1
,
r
]
[mid+1,r]
[mid+1,r]的价值,故意不选[l,mid])
51nod1686
二分答案mi,题目变成了求有是否存在>=k个区间满足众数个数>=mi,双指针(l,r) l从左到右,然后开个桶记一下出现次数,r表示离l最近的区间众数出现次数为mi的位置,O(n)扫一下就行了,然后此时(l,r)对应的答案就是n-r+1 (l固定,显然有n-r+1个区间满足条件)
HDU4734
一道水水的数位dp
注意分解十进制位之后要从高位往低位,而且必须是从
dfs(curx,rest,fg) --> dfs(curx-1,rest-i*2^{x-1},fg && (lim == i)
否则记忆化的时候会出错!qaq
BZOJ3732
虽然是kruskal重构树板子题,但是对operator<有了更深的认识
之前在写堆优dijk的时候,一般是这样:
这样些的话,边是从大到小排序的,为什么还是对的呢?因为priority_queue默认大根堆,也就是将大的值看成小的,这样就对了
但是这个重构树题要求边权从小到大,所以需要改成v<b.v
(记忆:将struct里的看成a,就是a.v<b.v)