24-2(计数)(19.12.29):
https://atcoder.jp/contests/agc035/tasks/agc035_f
https://atcoder.jp/contests/agc035/submissions/9203617
对于行i和列j,只有k[i]=j,l[j]=i-1,或k[i]=j-1,l[j]=i会重复。
所以容斥枚举一共有多少对行列是这样重复的即可:
(Ans=sum_{k=0}^{min(n,m)}C_n^k*C_m^k*k!*(n+1)^{m-k}*(m+1)^{n-k}*(-1)^k)
42-1(匹配+构造)(20.2.1):
https://codeforces.com/contest/547/problem/D
https://codeforces.com/contest/547/submission/69965423
方法1:
首先这是一个二分图,原来的点就是二分图上的边。
如果所有点的度数都是偶数,可以跑若干次欧拉回路。
回路上的边交替染色即可。
一个点是奇数的话,就随便断它的一条边。
之后接回去的时候看看颜色即可,这样显然差不超过1.
方法2:
点还是点。
对于x相同的,若有k个,则连k/2条边,边连接的点互不相同,k奇数的话剩下一个不用管。
y相同的同理。
这样染色,使每条边的两个点的颜色不同即可。
可以证明不会有冲突(奇环),因为走的边一定是x轴和y轴的边交替走,想要回来一定要走偶数条边。
45-1(计数+树形dp)(20.2.6):
https://codeforces.com/contest/512/problem/D
https://codeforces.com/contest/512/submission/70426270
先考虑哪些点是不合法的:
1.边双里的点
2.边双之间的路径上的点
找到这些点可以通过直接Turpo找。
那么剩下的点显然是个森林,我们把树分成两种:
1.有根树,即这棵树有一个点和不合法的点有连边(不可能有两个这样的点),那么这个点一定是这个树最晚取走的点,以它做根,对于每个子树同样满足这个性质,所以树形dp设(f[i][j])表示i为根的子树里选了j个点的方案数。
转移显然,主要i一定是最后一个点,所以(f[i][siz[i]]=f[i][siz[i]-1])
2.无根树, 就是没有那样的点的树。这个枚举每一个点做根,做那样的dp,把所有结果加起来,注意对每一个大小为x的子树,会被不属于这个子树的点作根时统计到一遍,所以除以(siz-x),当x=siz时不用除以。
复杂度由树形背包可得是(O(n^3))
39-1(推理讨论+ecgcd+最短路)(20.2.6)
https://codeforces.com/contest/516/problem/E
https://codeforces.com/contest/516/submission/46652574
杂题分享时淘过的,随便丢一篇题解:
https://blog.csdn.net/jokerwyt/article/details/103021688
12-3(动态规划+NTT)(20.2.7):
https://atcoder.jp/contests/agc021/tasks/agc021_f
https://atcoder.jp/contests/agc021/submissions/9937374
设(f[i][j])表示i行j列,其中i行一定不为空的方案数。
考虑新加一列,有k行在前j列的没有染色,在新加的这列有了染色。
当k=0时,只用考虑原来的j行对这一列的最小最大行影响:
(f[i][j+1]+=f[i][j]*(1+i+C(i,2)))
否则,考虑把k行插入原来的j行中,但是新的列的最大最小行还可能是原来的j行,分2*2=4种情况(即上下是否是原来的)可以得到系数
(f[i+k][j]+=f[i][j]*((C(i+k,k)+C(i+k,k+1)+C(i+k,k+1)+C(i+k,k+2))=C(i+k+2,k+2)))
最后(ans=sum_{i=0}^nC_{n}^i*f[i][m])
第二个转移可以NTT优化,时间复杂度:(O(nm~log~n))。
19-2(动态规划+xjb优化)(20.2.17):
https://codeforces.com/contest/708/problem/E
https://codeforces.com/contest/708/submission/71224703
考虑一行一行的转移,设(f[i][l][r])表示前i行联通,第i行剩[l,r]的概率和。
(f[i][l][r]=p[l][r]sum_{[u,v]∩[l,r]≠∅}f[i-1][u][v])
(p[l][r])表示一行k轮后剩([l,r])的概率。
设(v[i])表示一行的左边搞了i个概率,
(v[i]=p^i*(1-p)^{k-i}*C_{k}^i)。
(p[l][r]=v[l-1]*v[m-r])
直接做(O(n^5)),显然可以前缀和优化。
设(s)是(f[i-1])的二维前缀和,那么:
(f[i][l][r]=p[l][r]*(s[m][m]-s[l-1][l-1]-s[m-r][m-r]))。
(-s[m-r][m-r])是因为对称性。
发现用到的都是(s[x][x])这样的。
干脆直接维护(s[x][x])吧。
设(g[i][j]=sum_{x<=j}sum_{y<=j}f[i][x][y])
(g[i][j]=g[i][j-1]+sum_{x<=j}f[i][x][j])
(g[i][j]=g[i][j-1]+sum_{x<=j}p[x][j]*(s[m][m]-s[x-1][x-1]-s[m-j][m-j]))
(g[i][j]=g[i][j-1]+sum_{x<=j}v[x-1]*v[m-j]*(s[m][m]-s[x-1][x-1]-s[m-j][m-j]))
从小到大枚举j维护两个东西的和就可以了。