极其毒瘤的一天,全场十几个人爆零(包括我)。
这里放一下题解。(由于题目过于毒瘤+填坑+加强自己出的题的数据并没有写代码)
T1
题目大意:有若干堆石子,要求每次在一堆数量不为1的石子堆中取出石子,假设这堆石子的个数是x,那么允许取的个数为正整数d,要求d|x且d≠x,没法再取石子的一方输。 游戏初始有m堆石子,每堆石子的个数均为1到n之间的正整数。问有多少种可能的初始状态先手一定能获胜(认为石子堆是有顺序的),答案模998244353。 n<=10^50000,m<=10^18。
用数学归纳法(打表)发现 k 个石子组成的一堆 SG 值为 k 能够整除的 2 的最高次幂
对于n, m ≤ 52501,用一个简单的 DP 即可计算出答案。
对于n, m ≤ 10^18,容易发现上面的 DP 可以改成倍增 DP。
当 n 很大时,我们首先要用高精度计算出 1 到 n 中包含 2 的最高次 幂为 k 的个数,我们发现此时 log n 也达到了 3e5 级别,需要优化倍增 DP 的转移。高精度可能需要压位来提高效率
我们自然想到可以用 FWT 优化计算,倍增计算时直接用 FWT 的点积相乘即可。
T2
题目大意:一个长度为n 的序列由一个1到9的数字组成。q次操作:
操作1:选择一个子串[L,R],从这个子串中再次随机选择一个子串,答案等于把子串转成十进制数字的期望。
操作2:把子串子串[L,L+x] 用子串[R,R+x]替换。
n,q<=152501
很容易在 O(n) 的时间内计算出一段区间的数字和的期望。
操作二改动极小。 我们发现多维护一些信息就可以进行区间合并,用线段树维护一 下即可。
用可持久化 Treap 维护序列就可以支持操作二。 空间限制紧需要定期重构。
T3 51nod1623
正解:dp套dp
对于一个数,最小操作数的统计可以维护一个栈,从高位到低位依次考虑每一位,设当前数字为x,将栈里所有大于x的数字删除,如果此时栈里没有数字x则加入,并且答案+1。
数位dp,用一个二进制数来表示栈里有哪些元素。
这里只考虑1~R的计算。
设数字R有n位,a[i]表示第i位。
设某数第i位的数字为x,且x<a[i],且第i+1位~第n位数字与R相同,将这个数记为(i,x),
可以通过这个标准将数分类,最多18*9种分类。
对于一种分类,统计这种分类里有几个数符合题目要求。
计算出此时栈的状态和已累加的答案(即最小操作数),记为 t1,t2 , dp[t1][i−1][K−t2] 为这类里符合要求的数的数量(K为输入要求的最小操作数)。
dp[i][j][k] 表示当前栈里的元素状态为i,再填j位数字,使答案(即最小操作数)刚好再加k的方案数,这个可以通过枚举下一位数字转移得到。
总结
……
还是好好学习吧