简单声明 我是蒟蒻不会推式子... 所以我用的是乱搞做法... 大自然的选择 这里我用的乱搞做法被闪指导赐名为"自然算法",对于这种输入信息很少的概率题一般都很适用. 比如此题,对于一组\(n,m\),我们可以进行\(10^6\)次随机,每次随机\(n\)个\(0\sim1\)之间的实数表示这个点在圆上的位置,然后我们暴力判断,用一个变量\(t\)记录下合法次数. 然后我们输出\(\frac t{10^6}\)就能得出大致概率了. 找规律 显然,上面这个"自然算法"…
卢卡斯定理 题目中说到\(p\)是质数. 而此时要求组合数向质数取模的结果,就可以用卢卡斯定理: \[C_x^y=C_{x\ div\ p}^{y\ div\ p}\cdot C_{x\ mod\ p}^{y\ mod\ p}\] 也就是说,我们可以把\(x\)和\(y\)转化成两个\(p\)进制数,然后每一位分别求组合数后再乘起来. 所以问题来了,什么时候一个组合数的值模\(p\)为\(0\)? 由于它是质数,所以对于一个组合数\(C_a^b\),当且仅当\(a<b\)时它的值才会为\(0\)…
从暴力考虑转化题意 考虑最暴力的做法,我们枚举路径的两端,然后采用类似求树上路径长度的做法,计算两点到根的贡献,然后除去\(LCA\)到根的贡献两次. 即,设\(v_i\)为\(i\)到根路径上的边权异或和,那么\((x,y)\)的答案就是: \[v_x\ xor\ v_y\ xor\ v_{LCA(x,y)}\ xor\ v_{LCA(x,y)}\] 由于\(v_{LCA(x,y)}\ xor\ v_{LCA(x,y)}=0\),所以答案就是: \[v_x\ xor\ v_y\] 于是,题意就…
分治 首先,我们考虑分治处理此问题. 每次处理区间\([l,r]\)时,我们先处理完\([l,mid]\)和\([mid+1,r]\)两个区间的答案,然后我们再考虑计算左区间与右区间之间的答案. 处理的时候就需要分类讨论. 分类讨论 设\(Mn_x\)在\(l\le x\le mid\)时表示左区间的后缀最小值,\(mid+1\le x\le r\)时表示右区间的前缀最小值:\(Mx_x\)同理根据\(x\)的取值范围分别表示左区间的后缀最大值和右区间的前缀最大值. 考虑在左区间枚举左端点\(i…
树上背包 这应该是一道树上背包裸题吧. 众所周知,树上背包的朴素\(DP\)是\(O(nm^2)\)的. 但对于这种体积全为\(1\)的树上背包,我们可以通过记\(Size\)优化转移时的循环上界,做到\(O(nm)\)的. 呃,复杂度为什么是这样的我也很迷,证明我也不会啊... 代码 #include<bits/stdc++.h> #define Tp template<typename Ty> #define Ts template<typename Ty,typenam…
森林 考虑到题目中给出条件两点间至多只有一条路径. 就可以发现,这是一个森林. 而森林有一个很有用的性质. 考虑对于一棵树,点数-边数=\(1\). 因此对于一个森林,点数-边数=连通块个数. 所以,我们只要前缀和求出询问区间内的点数和边数,就可以计算出连通块个数了. 注意边数要分两个方向讨论,然后询问时注意防止越界. 代码 #include<bits/stdc++.h> #define Tp template<typename Ty> #define Ts template<…
\(2-SAT\) 考虑每个点只能选择\(R\)或\(B\),可以看作选\(0\)或\(1\). 然后对于给出的关系式,若其中一个位置满足关系式,另两个位置就必须不满足关系式,这样就可以对于每个关系式建出\(6\)条边. 然后就是裸的\(Tarjan\)求\(2-SAT\)一组解的板子了. 代码 #include<bits/stdc++.h> #define Tp template<typename Ty> #define Ts template<typename Ty,ty…
题意转化 考虑我们对于集合中每一个\(i\),若\(i-2,i+k\)存在,就向其连边. 那么,一个合法的集合就需要满足,不会存在环. 这样问题转化到了图上,就变得具体了许多,也就更容易考虑.求解了. 奇偶性讨论 这题对于\(k\)为奇数/偶数的情况,要分别处理. 由于偶数情况较为简单,所以我们从偶数讲起. 当\(k\)为偶数 这时我们发现奇数和偶数是独立的. 我们分别求出奇数和偶数的方案数(\(DP(\lfloor\frac{n+1}2\rfloor,\frac k2)\)和\(DP(\lfl…
莫比乌斯反演 考虑先推式子: \[\sum_{i=l}^r[gcd(a_i,G)=1]\] \[\sum_{i=l}^r\sum_{p|a_i,p|G}\mu(p)\] \[\sum_{p|G}\mu(p)\sum_{i=l}^r[p|a_i]\] 因此我们只要枚举询问的这个数的因数,然后求出这段区间内有多少个数是它的倍数即可. 分块 我们可以统计对于每个数,每个块内有多少个数是其倍数. 数的规模\(O(n)\),块大小\(O(\sqrt n)\),所以内存是\(O(n\sqrt n)\),询问…
二分 首先,可以发现,最后的答案显然满足可二分性,因此我们可以二分答案. 然后,我们只要贪心,就可以验证了. 贪心 不难发现,肯定会优先选择能提供更多插座的排插,且在确定充电器个数的情况下,肯定选择能经过排插数量最大的那些充电器. 所以,我们只要模拟插排插的过程,记录当前深度\(d\).插座数\(t\)即可. 设选择的能经过排插数量恰好为\(d\)的充电器有\(x\)个,则若\(t<x\),显然不合法. 否则,我们将\(x\)个位置插上充电器,其余位置尽可能地插排插,就可以了. 代码 #incl…
找规律 设\(p_i=a_{i+1}-a_i\),则答案就是\(\sum_{i=1}^{n-1}p_i\). 考虑若将\(a_i\)加上\(x\)(边界情况特殊考虑),就相当于是将\(p_{i-1}\)加\(x\),\(p_i\)减\(x\). 先考虑\(p_{i-1}\)加\(x\)所造成的影响: 当\(p_{i-1}\ge0\)时,就相当于将答案加上\(x\). 当\(-x\le p_{i-1}<0\)时,原先的答案是\(-p_{i-1}\),新的答案是\(x+p_{i-1}\),所以答案加…
树形\(DP\) 考虑设\(f_{i,j,k}\)表示在\(i\)的子树内,从\(i\)向下的最长链长度为\(j\),\(i\)子树内直径长度为\(k\)的概率. 然后我们就能发现这个东西直接转移是几乎不可能的. 所以我们在转移时要开个辅助数组\(s_{op,x,y,k}\),其中\(op\)用于滚存,表示最长链为\(x\),次长链为\(y\),子节点子树内直径长度小于等于\(k\)的概率. 然后我们只要枚举子节点,再枚举子节点子树内的链长,就可以采用刷表法简便地\(DP\)转移了. 这样看似\…
线段树上\(DP\) 首先发现,每个数肯定是向自己的前驱或后继连边的. 则我们开一棵权值线段树,其中每一个节点记录一个\(f_{0/1,0/1}\),表示在这个区间左.右端点是否连过边的情况下,使这个区间符合条件的最小代价. 合并时考虑如果左儿子的右端点或右儿子的左端点中有一个没有连过边,就必须连边,否则就不连边. 然后我的写法比较蠢,不知道为什么当左右儿子中某个节点只有一个数时需要特判处理. 最后答案就是根节点的\(f_{1,1}\). 具体详见代码. 代码 #include<bits/std…
转化题意 这题目乍一看十分玄学,完全不可做. 但实际上,假设我们在原序列从小到大排序之后,选择开的宝箱编号是\(p_{1\sim Z}\),则最终答案就是: \[\sum_{i=1}^Za_{p_i}(p_{i+1}-p_i)\] 其中\(p_{Z+1}=n+1\). 有了这个式子,就可做了许多. 暴力\(DP\) 我们设\(f_{i,j}\)为在前\(i\)个宝箱中选择了\(j\)个宝箱的最小代价. 枚举一个转移点\(k\)表示上个选择的宝箱,就可以得到: \[f_{i,j}=f_{k,j-1…
莫比乌斯反演 血亏! 比赛时看到这题先写了个莫比乌斯反演,然后手造了几组数据和暴力对拍的时候发现,居然答案就是\(nm\)... 吐槽数据范围太小... 下面给上出题人对此题的解释: 原式的物理意义,就是从坐标原点(0,0),用每一种合法的斜率,穿过坐标[1~n,1~m]的方阵中的整点的个数,总数即 n*m. 代码 #include<bits/stdc++.h> #define Tp template<typename Ty> #define Ts template<type…
暴力\(DP\) 这题做法很多,有\(O(n^2)\)的,有\(O(n^2logn)\)的,还有徐教练的\(O(nlogn)\)的,甚至还有\(bzt\)的二分+线段树优化建图的费用流. 我懒了点,反正数据范围这么小,就写了个\(O(n^2)\)的暴力\(DP\). 先将两个数组都排序,一个显然的性质,就是人选择钥匙时不可能相交. 所以我们设\(f_{i,j}\)表示前\(i\)个人选择了前\(j\)把钥匙时所用最大时间的最小值. 转移也很简单. 代码 #include<bits/stdc++.…
\(IDA^*\) 说实话,这道题我一开始没想出正解,于是写了一个\(IDA^*\)... 但神奇的是,这个\(IDA^*\)居然连字符串长度分别为\(2500,4000\)的数据都跑得飞快,不过数据发下来之后我测了一下只有45分. 就在不断优化\(IDA^*\)的过程中,我突然就想出了正解的做法,看来以后遇事不决先暴力. \(DP\)求解第一个询问 考虑一个\(DP\),我们设\(f_{i,j}\)表示当前在第一个字符串中是第\(i\)位,第二个字符串中是第\(j\)位的最小步数. 若记录\(…
数位\(DP\) 首先考虑二进制数\(G(i)\)的一些性质: \(G(i)\)不可能有连续两位第\(x\)位和第\(x+1\)位都是\(1\).因为这样就可以进位到第\(x+2\)位.其余情况下,这个\(G(i)\)必然合法. 对于一对\(x,y\)满足\(x<y\),则\(G(x)<G(y)\). 则根据这些性质,我们就可以考虑数位\(DP\). 按照一般数位\(DP\)的套路,我们把对\(a\sim b\)的\(DP\)转化为对\(1\sim a-1\)和\(1\sim b\)的两个\(…
暴力\(DP\) 考虑暴力\(DP\),我们设\(f_{i,j}\)表示当前覆盖长度为\(i\),上一次折叠长度为\(j\)的方案数. 转移时需要再枚举这次的折叠长度\(k\)(\(k\ge j\)),转移方程如下: \[f_{i+2k-j,k}+=f_{i,j}\] 对于左.右两边,根据不同的初始化\(DP\)两遍. 统计时枚举两边覆盖长度计算即可. 优化\(DP\) 实际上,我们可以把这个\(DP\)拆成两个数组,一个表示左端点在\(x\)位的方案数,另一个表示右端点在\(y\)位的方案数.…
树形\(DP\) 实际上,这道题应该不是很难. 我们设\(f_{x,i,j}\)表示在以\(x\)为根的子树内,原本应输出\(i\),结果输出了\(j\)的情况数. 转移时,为了方便,我们先考虑与,再考虑非,即先转移,再交换\(f_{x,0,0}\)和\(f_{x,1,1}\),\(f_{x,1,0}\)和\(f_{x,0,1}\). 这样一来,转移方程如下: \[f_{x,i1\&i2,j1\&j2}=\sum f_{x,i1,j1}*f_{son,i2,j2}\] 然后,在转移结束,交…
2019/4/9 TGDay2模拟赛 今天是\(TG\)模拟赛的第二天了,试题难度也是相应地增加了一些,老师也说过,这就是提高组的难度了.刚开始学难的内容,一道正解也没想出来,不过基本的思路也都是对了,暴力分也都拿到了. 还是看一下试题安排: 题号 试题分组 考察算法 思维难度 代码难度 1 \(T1\) 数学推导+性质分析+枚举优化 ★★★ ★★ 2 \(T2\) 最短路+搜索 ★★ ★★★ 3 \(T3\) 三分法求函数极值+树状数组 ★★★ ★★★ 感觉难度还是大的,但是在考试的时候竟然\…
2019/4/8 TGDay1模拟赛 这次是和高一的学长学姐们一起参加的\(TG\)模拟考,虽然说是\(Day1\),但是难度还是很大的,感觉比\(18\)年的\(Day1\)难多了. 还是看一下试题安排: 题号 试题分组 考察算法 思维难度 代码难度 1 \(T1\) 数学推导 ★★ ★ 2 \(T2\) 分块+推导 ★★★ ★★★ 3 \(T3\) ST表+分治 ★★★ ★★ 这次题目真的很难啊,\(T1\)是没有想到好好去推的,\(T2\),\(T3\)基本全挂了. 时间安排感觉又不行了,…
模拟赛T2 交换 解题报告 题目大意: 给定一个序列和若干个区间,每次从区间中选择两个数修改使字典序最小. \(n,m\) 同阶 \(10^6\) 2.1 算法 1 按照题意模拟,枚举交换位置并比较. 时间复杂度\(O(mn3)\). 期望得分20分. 2.2 算法 2 不难发现给定区间之外的位置对每个询问的答案无影响,所以每次的问题就是取出一个子段,问这个子段怎样交换一次字典序最小. 根据字典序定义,我们需要找到最小的位置满足通过交换可以使这个位置变小,也就是说这个位置不是后缀最小值,因此从后…
找环 考虑每次洗牌其实是一次置换的过程,而这样必然就会有循环出现. 因此我们直接通过枚举找出每一个循环,询问时只要找到环上对应的位置就可以了. 貌似比我比赛时被卡成\(30\)分的倍增简单多了? 代码 #include<bits/stdc++.h> #define Tp template<typename Ty> #define Ts template<typename Ty,typename... Ar> #define Reg register #define RI…
这次模拟赛真的,,卡常赛. The solution of T1: std是打表,,考场上sb想自己改进匈牙利然后wei了(好像匈牙利是错的. 大力剪枝搜索.代码不放了. 这是什么神仙D1T1,爆蛋T1,好像A了它或拿分的就几个人,, The solution of T2: 题解是这么写的:和八皇后很像,八皇后是x+y和x-y来判重,这里就k1x+k2y来判重. 从各个点引出直线,带入原点检验方程即可. 注: x/y = Δx/Δy x*Δy = Δx*y 下面代码用了这个原理,省去了gcd(或…
2.追捕 [题目背景] Duan2baka:“jmsyzsfq天下第一蠢!” jmsyzsfq:“你说什么?!” [题目描述] 于是Duan2baka开始了逃亡的旅程,而jmsyzsfq也开始追捕Duan2baka.  他们来到了一个有n个节点的有向图,迅速逃跑的Duan2baka会首先降落在有向图的某个节点T上,因为怕发出声音,他会永远静止不动.而随后跟来的jmsyzsfq会降落在图上随机一个节点S上(可以与T相同),并可以沿着图中的有向边随意走动.因为jmsyzsfq有着敏锐的嗅觉而且绝顶聪…
昨天 ych 的膜你赛,这道题我 O ( n4 ) 暴力拿了 60 pts. 这道题的做法还挺妙的,我搞了将近一天呢qwq 题解 60 pts 根据题目给出的式子,四层 for 循环暴力枚举统计答案即可: #include<iostream> #include<cstdio> using namespace std; int read() { char ch=getchar(); ,x=; ') { if(ch=='-') x=-x; ch=getchar(); } ') { a=…
题目大意: 已知三个$n$位二进制数$A$,$B$,$C$. 满足: $A+B=C$ 它们二进制位中$1$的个数分别为$a$,$b$,$c$. 求满足条件的最小的$C$. Solution 唉,又是一道随缘猜结论的题,可惜极限数据卡掉了我一个点,开大数组就A了..... 通过$n \leq 10$的打表,我们发现所有的最优解中都有一种情况是$A$的二进制位的$1$是连续一段. 事实上,真的就是这样的! 设$t=a+b-c$,显然,$t$表示加法过程中进位的次数. 我们设$A$的$a$个$1$是连…
设阈值 考虑对于询问的\(d\)设阈值进行分别处理. 对于\(d\le\sqrt{max\ d}\)的询问,我们可以\(O(n\sqrt{max\ d})\)预处理答案,\(O(1)\)输出. 对于\(d>\sqrt{max\ d}\)的询问,我们可以爆枚其倍数.然后就变成询问一个区间内一些数的个数,可以考虑用莫队.考虑到移动和询问的根号是分开计算的,所以复杂度是\(O(q(\sqrt n+\sqrt{max\ d}))\). 代码 #include<bits/stdc++.h> #de…
Weed duyege的电脑上面已经长草了,经过辨认上面有金坷垃的痕迹. 为了查出真相,duyege 准备修好电脑之后再进行一次金坷垃的模拟实验. 电脑上面有若干层金坷垃,每次只能在上面撒上一层高度为 vi 的金坷垃,或者除掉最 新 vi 层(不是量)撒的金坷垃.如果上面只留有不足 vi 层金坷垃,那么就相当于电脑上 面没有金坷垃了. duyege 非常严谨,一开始先给你 m 个上述操作要你依次完成.然后又对实验步骤进行 了 q 次更改,每次更改都会改变其中一个操作为另外一个操作.每次修改之后都…