其实省选在四天前就已经结束了,但因为题目难度略大我到今天上午才补完全部题目……(捂脸逃)考场上很幸运,打完了全部我会写的部分分,最后Round1的110分 + Round2的70分,勉强算是没有被联赛day2的文件夹坑太多。。。
git
目前网上比较容易找到的题解彷佛只有ydc教主的这份:http://ydc.blog.uoj.ac/blog/336,不过对于我这种水平的人来讲这份题解还不是很好理解,那么我再来稍微补充一点更基础的内容吧。。
算法
有一棵点数为N的树,树边有边权。给你一个在0~N以内的正整数K,你要在这棵树中选择K个点,将其染成黑色,并将其余的N-K个点染成白色。将全部点染色后,你会得到黑点两两之间的距离加上白点两两之间距离的和的收益。问收益最大值是多少。 数组
其中$1 \leq N \leq 2000, 0 \leq K \leq N$。
ide
从点和点的距离入手不太好分析……我在考场上想了一两个小时最后仍是弃疗了,连暴力都没心情写,交了一份靠运气的贪心骗分。
函数
其实呢……因为树上每一条边都是桥,咱们能够从每一条边两端的黑白点数入手,也就是考虑每条边对答案形成的贡献。定义函数f(v, i)表示在v子树中,共将i个点染色后,能获得的“子树中全部点的父边的对答案的贡献之和”的最大值。这样每棵子树就成了一个可分割的子结构,就能够作树形背包了。
spa
根据官方题解中给出的那种神奇的证实,这样作的时间复杂度是$O(N^2)$.指针
有一棵点数为N的树,以点1为根,且树点有边权。而后有M个操做,分为三种: code
操做1 1 x a:把某个节点x的点权增长a。 blog
操做2 2 x a:把某个节点x为根的子树中全部点的点权都增长a。 游戏
操做3 3 x:询问某个节点x到根的路径中全部点的点权和。
对于100%的数据,N,M<=100000,且全部输入数据的绝对值都不会超过10^6
其实咱们这样来看……对于一次操做(2 u x),咱们来考虑此次操做对u的某个后代v的贡献。不难看出,从u到v路径上的每一个点的权值都被增长了x,这个操做对v的答案的增量$d_v = (dist(u, v) + 1) * x$ 。然而dist(u, v)这个东西彷佛不太容易做为区间修改的增量。因为u是v的祖先,咱们不妨把dist拆一下,那么$d_v = (dep_v - dep_u + 1) * x$,或者$d_v = dep_v * x - (dep_u - 1) * x$.(其中$dep_i$表示i点到根的距离)这时咱们其实已经把此次操做的贡献拆成了一个关于点v的深度的一次函数,那么每次进行操做时只要分别修改两项的系数就能够了。
有一个长度为N的数组,甲乙两人在上面进行这样一个游戏:
首先,数组上有一些格子是白的,有一些是黑的。而后两人轮流进行操做。每次操做选择一个白色的格子,假设它的下标为x。接着,选择一个大小在1~n/x之间的整数k,而后将下标为x、2x、...、kx的格子都进行颜色翻转。不能操做的人输。
如今甲(先手)有一些询问。每次他会给你一个数组的初始状态,你要求出对于这种初始状态他是否有必胜策略。假设两人总能作出最优决策。
对于30%的数据,N<=20;
对于50%的数据,N<=1000000;
对于70%的数据,N<=10000000;
对于100%的数据,N<=1000000000,K,W<=100,不会有格子在同一次询问中屡次出现。
好难啊……TAT考场上果断30分暴搜……
出题人kzf告诉咱们,能够修改一下游戏的定义:每一步能够选择黑格子或白格子,最终能将全部格子都翻成黑色的人赢。因为每次翻转黑格子的操做都不可能直接带来胜利,而任何一步选取黑格子进行的有利操做都能由对方经过再翻一次这个格子抵消掉,根据假设“两我的都是足够聪明的”,咱们知道游戏中必定不会有人选择黑格子。这就保证了这种转换的正确性。
所以咱们能够把每一个黑色的位置都当作偶数个白格子叠加起来获得的,并将每一个位置当作一个独立的游戏来计算SG函数,就能够套用常规的博弈题思路了。根据游戏规则,咱们有$$SG(i) = \mathop{mex} \limits_{1 \leq k \leq N / i} \{ \mathop{\oplus } \limits_{2 \leq t \leq k} \{ SG(t*i) \}\}$$(其中mex(S)表示S中没有出现的最小天然数)按定义递推就能够拿到50分了。
考虑到当一个点i走到N要跳的步数必定时,咱们能够把这些i的倍数的序列映射到另外一个序列2...N/i,这样咱们就能够用数学概括证实每一个点i的SG值只与从它跳到N须要的次数(即 N / i)有关。而后咱们能够注意到,i从1到N中,N / i只会有O($\sqrt{N})$种取值,因此咱们只需递推$O(\sqrt{N})$轮就能够了。然而……在递推时不管是维护一个指针线性递推仍是用二分查找结构在线查找都只能拿到70分……
而后出题人kzf又告诉咱们,存在不少相邻的按N/i划分的区间有着相同的SG值(缘由大概是跳动次数增长时多跳的那一次改变的那些SG和不容易刚好等于增长以前的SG值?反正我不会证实……)。因此咱们在预处理时只要判断是否能和上一块合并就能够了。复杂度……嗯……大概是O(玄学 × $N$)。不过实际跑起来仍是挺快的……
Update: 考虑上面说的70分算法,在递推的过程当中咱们须要尽量快地查询之前求出的SG值,那么咱们直接用一个哈希表就能够解决问题了!(我之前还没写过哈希表……太弱啦……)时间复杂度大概是$T(N) = \sum_{i=1}^{\sqrt{N}} (\sqrt{\frac{N}{i}} + \sqrt{i} ) × \frac{N}{P}$,这个求出来大概是$O(\frac{N^{\frac{7}{4}}}{P})$,总算是不用玄学完美地解决了= =
刚开始你有一个数字0,每一秒钟你会随机选择一个[0,2^n-1]的数字,与你手上的数字进行按位或(C和C++的|,Pascal的or)操做。
选择数字i的几率是p[i]。保证0<=p[i]<=1,∑p[i]=1
问指望多少秒后,你手上的数字变成2^n-1。
对于30%的数据,n<=10
对于60%的数据,n<=15
对于100%的数据,n<=20
考场上我写了个错误的递推,不过我几率论学得渣不知道为何不对,总之我在考场上尝试了好久都跑不出样例,最终直接输出个INF就放那了= =
换个思路,咱们尝试用常规的指望的定义来求。设函数$f_k (S) $为第k轮集合为S的几率,那么答案就是
$$\sum_{i=1}^{\infty} i * (f_i (U) - f_{i-1} (U) )$$
不难写出函数f的递推式:
$$f_{i+1}(S) = \sum_a \sum_b [a \cup b = S] f_{i}(a) * P(b)$$
不过这个式子看上去不太好转移对吧?咱们能够给它加个特技,不要管它们的并集是谁了,咱们直接来考虑等式两边S集合的全部子集的函数值之和(这步变换能够经过集合论中的莫比乌斯反演来逆转),即:
$$\sum_{s' \subseteq S} f_{i+1}(s') = \sum_{a \subseteq S} \sum_{b \subseteq S} f_i(a) * P(b)$$
或$$\sum_{s' \subseteq S} f_{i+1}(s') = (\sum_{a \subseteq S} f_i(a) ) (\sum_{b \subseteq S} P(b))$$
发现了什么吗?某一项在一个集合上的答案的子集和刚好等于前一项上同一集合的子集和与这一集合的初始几率函数(也就是f_1函数)的子集和的乘积。换句话说,若是咱们设$F_i (S) = \sum_{s' \subseteq S} f_i (s')$,那么咱们的转移方程就能够写成$F_{i+1}(S) = F_i (S) * F_1 (S) $。瞬间变得很是简单有木有!!!什么求和都没有了,咱们马上就能够获得F的通项公式:$F_i (S) = (F_1 (S)) ^ i$.
那么如今咱们的$F_i$函数就已知了,咱们来看看怎么由$F_i$函数推出$f_i$。咱们不妨令$f_i (S) = \sum_{S' \subseteq S} \mu(S', S) F_i(S')$,其中$\mu(S', S)$是咱们要求的莫比乌斯函数(注意这里指的是集合论中广义的莫比乌斯反演)。将F代入,可得
$$f_i(S) = \sum_{S' \subseteq S} \mu(S', S) \sum_{S'' \subseteq S'} f_i(S'')$$ 由容斥原理能够得出,$\mu(S', S) = (-1)^{|S| - |S'|}$。从而咱们能够获得:$$f_i (S) = \sum_{S' \subseteq S} (-1)^{|S| - |S'|} F_i(S')$$.代入$F_i$(S')的通项公式,可得:$$f_i(S) = \sum_{S' \subseteq S} (-1)^{|S| - |S'|} (F_1 (S')) ^ i)$$
那么咱们的最终答案就能够表示为
因为F函数不会超过1,可直接利用幂级数求和得出答案:$$ \sum_{S' \subseteq S} (-1)^{|S| - |S'|} * ( \frac{1}{F_1(S') - 1} ) $$
而计算一个函数的子集和函数能够用标程中给出的代码用$O(n2^n)$的时间复杂度求出。这样,这道题就完美解决啦!
你有一个长度为n的数字串。
定义f(S)为将S拆分红若干个1~m的数的和的方案数,好比m=2时,f(4)=5,分别为4=1+1+1+1, 4=1+1+2, 4=1+2+1, 4=2+1+1, 4=2+2
你能够将这个数字串分割成若干个数字(容许前导0),将它们加起来,求f,并求和。
好比g(123)=f(1+2+3)+f(1+23)+f(12+3)+f(123)。
已知字符串和m后求答案对998244353(7*17*223+1,一个质数)取模后的值。
对于30%的数据,字符串长度不超过5
对于60%的数据,字符串长度不超过18
对于100%的数据,字符串长度不超过500,m<=5
不难看出,$f(i) = \sum_{j=1}^m f(i-j)$.很容易把这个递推式写成一个m × m的矩阵M。暂时撇开f函数前m项构成的向量$F_0$,咱们考虑对这整个转移矩阵作dp。设g(i)表示可以将$F_0$转移到$F_{num_{0, i}}$的转移矩阵。其中$num_{i, j}$表示字符串的第i+1到j位构成的十进制数。
根据矩阵乘法对加法的分配律,能够获得$g(i) = \sum_{j = 0}^{i-1} g(j) * M ^ {num(j, i)}$,先用十进制矩阵快速幂的思路求出F的10的各幂次的幂,而后dp求出最终的矩阵,最后左乘向量求值便可。总复杂度$O({len}^2 m^3)$ 。值得注意的是……这题卡常数,矩阵乘法必定要尽可能减小取模的次数。