22-3(19.11.9)(计数):
https://atcoder.jp/contests/arc096/tasks/arc096_c
https://atcoder.jp/contests/arc096/submissions/8343796
mdzz复杂度就多了个\(n\)难受啊。
考虑算\(>=2\)次显然非常地难算。
所以肯定是容斥有多少个不合法的。
于是我就想到枚举\(x,y\)表示至少有\(x\)个\(0\)次的,\(y\)个\(1\)次的方案数。
容斥系数显然是\((-1)^{x+y}\)。
考虑在枚举个\(j\)表示把\(y\)个分到了\(j\)个集合,系数是\(S_{y,j}\)
剩下的东西,自己可以成集合,\(2^{2^{n-x-y}}\)。
也可以加入这\(j\)个集合,\((2^{n-x-y})^j\)。
得到了\(O(n^3)\)做法,不会优化。
然后发现,\(x,y\)是可以一起枚举的,枚举\(x+y\),系数变成了\(S_{x+y+1,j+1}\),哭了。
34-3(19.11.9)(dp):
https://atcoder.jp/contests/agc026/tasks/agc026_d
https://atcoder.jp/contests/agc026/submissions/8358342
考虑有两个等长相邻的列,已经确定了左边,现在要确定右边。
容易发现,当左边没有任意两个相邻相同时,方案数是2,否则是1。
由此不难思考出一个dp:
设\(f[i][j]\)表示前\(i\)列搞完了,第i列的最低相同点在\((H[j-1],H[j]]\)间的方案数(H是h排序去重后的数组)。
讨论一下即可得到方程。
直接做是\(O(n^3*log~n)\),发现可以优化到\(O(n^2)\),懒得改了,所以\(n=100?\)。
25-3(19.11.9)(容斥+树上背包):
https://atcoder.jp/contests/arc101/tasks/arc101_c
https://atcoder.jp/contests/arc101/submissions/8370764
直接dp可能有点难搞。
不妨考虑容斥,如果至少有x条边没有被遍历,那么系数是\((-1)^x\)。
这x条边会把整棵树割成若干联通块,每个联通块内随便连。
预处理\(g[n]\)表示n个点随便乱连的方案数:
\(g[n]=g[n-2]+g[n-4]*(n-2)*(n-3)\)
那么考虑用树上背包去实现容斥的过程,\(f[i][j]\)表示以i为根子树中,以i为根的联通块有j个点,每次可以转移上面,或者把联通块独立。
9-3(19.11.10)(dp)
https://atcoder.jp/contests/arc101/tasks/arc101_d
https://atcoder.jp/contests/arc101/submissions/me
考虑转换成一个新问题,每个点变为\((c[i],d[i])\)表示向左向右的距离。
一开始在\((0,0)\),每次可以走到\((x+1,y)\)或\((x,y+1)\),经过一个时就确定了,问方案数。
也可以看做走这样一条的折线:\(x1
18-3(19.11.17)(二分):
https://atcoder.jp/contests/agc029/tasks/agc029_c
https://atcoder.jp/contests/agc029/submissions/8503833
二分答案,然后每个串肯定填大于前面字符串的字典序最小的串。
维护每个串选了什么,相同的一段字符缩到一起,然后搞一搞就好了。
27-3(19.11.17)(构造):
https://atcoder.jp/contests/agc028/tasks/agc028_c
https://atcoder.jp/contests/agc028/submissions/8506342
那个\(min(a[x],b[y])\)有点烦人,因为最终答案也是求\(min\),不如改成二选一,这样会变得可做一些。
然后考虑每条边是选左边还是右边。
首先有两种合法的方案:
1.全部选左边。
2.全部选右边。
3.除了1、2的情况,考虑选边交界处,这种情况下显然没有被一条边选的点的个数=被两条边选的点的个数\(>0\)。
首先任意选边都有:没有被一条边选的点的个数=被两条边选的点的个数
所以枚举一个被两条边选的点,保证至少选了一个,再从剩下的权值中选n-2个最小的就好了。
39-3(19.11.18)(构造):
https://atcoder.jp/contests/agc027/tasks/agc027_d
https://atcoder.jp/contests/agc027/submissions/8509087
不妨使m=1。
黑白染色,使白的格子是周围四个黑格的lcm+1。
那么如何让所有格子互不相同且四个黑格的lcm较小。
以\(x+y\)和\(x-y\)来划分,黑格的数是它所在的正对角线和负对角线的质数乘积。
至少需要1000个质数,而白格最多是四个质数的乘积,\(p[1000]^4<10^{15}\)。
14-1(19.11.19)(网络流):
https://codeforces.com/contest/611/problem/H
https://codeforces.com/contest/611/submission/65335041
考虑定1为根,则接下来的每条边都要匹配一个点,存在完美匹配是必要条件。
做出一个匹配后,每条边就已经确定了一个点的编号。
另外一个的点其实可以随便确定,只要是个树就好了。
所以直接从1开始bfs,若不能遍历到所有的点也没有解。
15-3 (19.11.20)(构造):
https://atcoder.jp/contests/arc102/tasks/arc102_d
https://atcoder.jp/contests/arc102/submissions/8534636
考虑倒着来,对1,2,3……,n进行交换。
假设交换了x-1,x ,x+1,变成了x+1,x,x-1。
可以得到的结论是x+1不可能再变回右边去,x-1不可能再变会左边去,这很显然。
设\(b[i]\)表示i出现p的\(b[i]\)位置,把i->b[i]这一段视为相关连续段,然后不断合并,得到极小相关连续段。
然后维护p[1-?]的min值和max值即可提出每一段相关连续段,设为l,l+1,……,r。
可以发现,对于x=l+1,l+3,……,有p[x]=x。
剩下的位置,互相之间会交换,通过手玩发现,一个点的移动方向是固定的,同一移动方向的点不能有超越的情况。
即,对于所有向右的点(包括不动的),要到的位置随原位置递增而递增。
即,对于所有向左的点(包括不动的),要到的位置随原位置递增而递增。
41-3(19.11.20)(树形dp):
https://atcoder.jp/contests/arc097/tasks/arc097_d
https://atcoder.jp/contests/arc097/submissions/8537365
非常容易的树形dp。
首先如果叶子是黑点删了,因为走进去不会更优。
直到所有叶子都是白点。
若直接从一个起点开始走回来,\(Ans=2*(D-1)+\sum !((r[x]\&1)xor ~color[x])\)。
若选一个起点和终点,则这条路径上的点除了终点以外反色,同时还少走len-1个点。
那么随便选一个根,记录f、g分别为子树里选起点、终点能是ans减少的最大值。
每次合并两个子树,同时更新f、g。
30-3(19.11.27)(计数、动态规划):
https://atcoder.jp/contests/arc100/tasks/arc100_d
https://atcoder.jp/contests/arc100/submissions/8672436
正难则反,考虑求不合法的。
当m个里本来就有k的连续段时,不合法的=0。
当这m个不是互不相同时,左右独立,所以做一个dp:
\(f[i][j]\)表示长度为\(i\)了,最长连续段是j的方案数,前后的区别是初值不同,做两次最后统计即可。
转移显然,可以前缀和优化。
当m个互不相同时,比较复杂,这m个是哪些数没有关系,问题转换为:
求长度为n时,合法的染色中,长度为m的连续段的出现次数,答案除以\(k!/(k-m)!\)即可。
依然是转换成不合法,还是之前的dp,多记一个长度为m的连续段的出现次数即可。
46-3(19.11.27)(数学几何结论题):
https://atcoder.jp/contests/agc039/tasks/agc039_d
https://atcoder.jp/contests/agc039/submissions/8674584
不想做,直接抄结论的。
https://blog.csdn.net/qq_39972971/article/details/102314467
37-3(19.11.28)(hash):
https://atcoder.jp/contests/arc099/tasks/arc099_d
https://atcoder.jp/contests/arc099/submissions/8679503
直接hash即可,注意要有逆元。
7-3(19.11.28)(构造):
https://atcoder.jp/contests/arc103/tasks/arc103_b
https://atcoder.jp/contests/arc103/submissions/8680192
首先所有点的x+y的奇偶性必须相同,这是个必要条件。
考虑用二进制构造,发现用\(1,2,4,...,2^x\)就可以搞出\(|x|+|y|<2^x\)的奇点,从大到小每次往曼哈顿距离减小的走即可。
偶数的加个1就好了。
28-2(19.11.28)(图论推理):
https://atcoder.jp/contests/agc032/tasks/agc032_c
https://atcoder.jp/contests/agc032/submissions/8680576
有奇点不行。
有一个度数>4的就显然可以。
全部都<4显然不行。
如果只有一个=4,显然也不行。
如果有>2个=4的,显然可可以。
如果有2个=4的,A能不经过B走回自己就行。
3-1(19.11.28)(几何):
https://codeforces.com/contest/575/problem/E
https://codeforces.com/contest/575/submission/65901303
考虑把有效面积的凸包建出来。
显然一定有三个点组成的圆包含所有的区域,证明通过一个大圆不断缩小刚好卡住。
然后
考虑凸多边形上相邻三个点产生的圆会大一些。
好像是取产生最大半径的三个点一定能包含住其它点,不会证明。
45-2(19.11.30)(分析+可持久化线段树):
https://atcoder.jp/contests/agc028/tasks/agc028_e
https://atcoder.jp/contests/agc028/submissions/8702574
首先肯定是逐位确定每一位是0还是1.
问题在于确定了一些状态后,如何判断是否有解。
考虑有解的话,有一种一定有一边新选的high elements全部是原最大点,因为如果两边都有非原最大点且成为high elements,可以交换把它们都去掉。
假设A选的全是原最大点。
设一共剩q个原最大点,A本来有u1个high elements,B本来有u2个high elements,B新选b个原最大点,B一共增加了c个high elements。
则u1+q-b=u2+c
u1-u2+q=c+b
即从剩下的中选一个递增序列,原最大点权值是2,非原最大点权值是1,分奇偶是权值最大再判判。
反过来假设B选的全是原最大点再做一遍。
41-2(19.11.30)(线段树合并):
https://codeforces.com/contest/671/problem/D
https://codeforces.com/contest/671/submission/66011186
线段树合并裸题,不讲了。
35-2(19.12.1)(几何):
https://codeforces.com/contest/698/problem/D
https://codeforces.com/contest/698/submission/66082529
精度把我搞傻了.jpg
考虑求出共线关系后,只需要7!枚举一个打击顺序,用一个bfs模拟一下打击就好了。
23-3(19.12.1)(sg函数结论题):
https://atcoder.jp/contests/arc091/tasks/arc091_d
https://atcoder.jp/contests/arc091/submissions/8722903
辣鸡结论,辣鸡题解,一个归纳搞定,辣鸡出题人。
\(y|x,f(x,y)=x/y\)
\(f(x,y)=f(x-(x/y+1),y)\)
随便加速一下即可。
45-3(19.12.1)(计数,动态规划):
https://atcoder.jp/contests/agc022/tasks/agc022_f
https://atcoder.jp/contests/agc022/submissions/8750998
对折是2x-y,也就是说每个点的系数都是\(±2^?\)。
因为权值差的太大,方案数就是系数的方案数。
考虑A关于B对称,A向B连一条有向边。
成了一棵内向树。
每个点的深度决定了是2的几次方。
正负取决于父亲的正负、儿子的个数、是父亲的第几个儿子。
父亲的正负可以去掉,变成于父亲是否相同。
然后考虑设\(f[i][j]\)表示确定了\(i\)个点,叶子中有\(j\)个的儿子数要是奇数。
枚举下一层的点的个数k,\((k-j)~mod~2=0且k>=j\)。
那么一开始有\(x0=(k-j)/2+j\)个系数是0,\(x1=(k-j)/2\)个系数是1.
考虑再枚举下一层的系数是0的点的个数\(u\)。
那么儿子数是奇数的点的个数恰好是\(|x0-u|\),注意不能多选2、4、6……来抵消,这样会被重复计数。
时间复杂度:\(O(n^4)\)。
1-3(19.12.2)(构造):
https://atcoder.jp/contests/arc103/tasks/arc103_d
https://atcoder.jp/contests/arc103/submissions/8755475
考虑相邻两个点\(x,y\),\(d[y]=d[x]+siz[x]-siz[y]\)
先找到最小的点作为叶子,然后找它的父亲。
那么它的父亲的\(dis\)是知道的,看有没有就好了。
就这样一直扫下去,最后判根(重心)可不可以。
17-1(19.12.2)(最短路+博弈+动态规划):
https://codeforces.com/contest/536/problem/D
https://codeforces.com/contest/536/submission/66158532
跑完最短路后,设\(f[i][j]\),表示A已选了距离前i的,B已选了距离前j的,A现在先手,先手-后手的最大值。
\(g[i][j]\)同理表示B先手。
然后需要预处理很多东西来转移。
11-3(19.12.2)(一维数轴问题):
https://atcoder.jp/contests/agc022/tasks/agc022_d
https://atcoder.jp/contests/agc022/submissions/8765433
对着题解超了一波,我现在都还很迷。
27-1(19.12.3)(贪心):
https://codeforces.com/contest/521/problem/D
https://codeforces.com/contest/521/submission/66205940
考虑顺序一定是赋值->加法->乘法。
赋值只取最大且>a[i]的,看做x-a[i]的加法。
然后加法和乘法可以贪心的搞搞,加法也看做乘法。
最后排序取前m大。
注意要用long double来判断分数的大小。
19-3(19.12.3)(计数dp):
https://atcoder.jp/contests/arc093/tasks/arc093_d
https://atcoder.jp/contests/arc093/submissions/8772591
非常简单的计数题。
考虑把1就固定在1的位置,最后答案乘一个\(2^n\)。
然后1的每一个祖先的另一个子树的大小分别为\(2^0,2^1,…,2^{n-1}\)。
这些子树里最小的会win出来和1 PK。
我们希望不要翻车,那么容斥有多少个翻车的,然后再分配一下是哪个子树,再从大到小分配一下标号。
用状态dp实现这个过程即可。
10-3(19.12.4)(图论):
https://atcoder.jp/contests/arc092/tasks/arc092_d
https://atcoder.jp/contests/arc092/submissions/8790068
有一条边x->y
考虑x能不走这条边走到y,且y不能走到x,则点双数+1.
x不能不走这条边走到y,且y能走到x,点双数-1.
问题在于判断x能否不经过这个边走到y。
假设x为入点的边,出点分别为:d1,d2,…,d0
不经过y,就一定要经过其它的点。
所以顺着扫一遍,求它们不经过x能走到那些点,再倒着扫一遍即可。
15-2(19.12.14)(暴力):
https://codeforces.com/contest/666/problem/D
https://codeforces.com/contest/666/submission/66811506
枚举每一个点保留哪一维,再枚举谁是哪个角。
二分个答案就变成了一堆区间交问题。
32-3(19.12.21)(推理):
https://atcoder.jp/contests/agc025/tasks/agc025_f
https://atcoder.jp/contests/agc025/submissions/9036598
考虑只有两个(1,1)才会一直加下去,遇到(1,0)或(0,1)时会发生神奇的改变。
低位的(1,1)永远追不上一个高位(1,1)。
所以从高到低考虑,用一个栈记录(0,1)和(1,0)的位置,由于每一次相遇一定可以减少至少一个1,所以时间复杂度是:\(O(n)\)
31-3(19.12.28)(构造):
https://atcoder.jp/contests/agc020/tasks/agc020_d
https://atcoder.jp/contests/agc020/submissions/9185635
答案一定是\(\lceil max(a,b)/(min(a,b)+1)\rceil\)。
想了很多贪心发现都不对,不如直接逐位确定:
我们需要保证,尽量填'A',任意时候剩下的\(a0,b0\)都满足上面的条件,且当前连续的A不超过k个。
这样得到一个\(O(n)\)的做法。
接着,考虑一直都是k个a,1个b,直到一个分界点,不能这样了,只能填b了。
那么这个分界点以后一定是:
先把多的b0-a0*k个b排掉。
之后就是1个a,k个b的形式。