【错解】
首先猜想和最大值有关,然而样例都凑不出来
然后开始瞎搞,从大往小拆成两个没出现过的数的乘积
过了样例……
等等?好像最大有重复的?
然后真瞎搞
WA1+TLE9
期间想到二分,但并不知道怎么check,索性放弃
【正解】
二分
由于是阶乘,x!某个因数a出现次数为
(sum _{i=1}^{infty} [frac{x}{a^{i}}])
把读入的数分解,然后就可以check辣
T2:上升序列
(lis)
【问题描述】
给出一个长度为 m 的上升序列 A(1 ≤ A[i]≤ n), 请你求出有多少种 1...n 的排列, 满足
A 是它的一个 LIS.
【输入】
第一行两个整数 n,m.
接下来一行 m 个整数, 表示 A.
【输出】
一行一个整数表示答案.
【输入样例1】
5 3
1 3 4
【输出样例1】
11
【输入样例2】
4 2
3 4
【输出样例2】
5
【数据范围与约定】
对于前 30% 的数据, n ≤ 9;
对于前 60% 的数据, n ≤ 12;
对于 100% 的数据, 1 ≤ m ≤ n ≤ 15.
【错解】
一看数据范围就知道是暴搜
发现没有规律,怒写了个nlogn暴力check
用链表维护
没有减掉枝
AC6+TLE4
【正解】
为什么不能状压呢
首先回忆nlogn求法:
定义d[i]为长度为i结尾最小的子序列,然后二分插入来转移
即nlogn求时最后的那个数组
当然不是这么做的
设状态s表示选了那些数,s1表示d中哪些数出现了
举个生动形象的栗子:2 3 1 4……
s={1,1,1,1,0}
d={1,3}
s1={1,0,1,0,0}
因为d是单调增的,所以我们可以用s1来还原d
即如果s1[i]为1,那么i在d中出现的位置为1~i的1的个数
然后可以(f(s,s1))定义状态
然后枚举插入一个数,就可以转移了
具体操作:插入i时,前面有k位
s|=i
s1前k位转成d,再把后面接上
如在3、1之间插入5
s={1,1,1,1,1}
s1不变
边界:当s为全集时,(f(s,s1)=(d长度为原序列长度))
然而复杂度不可接受
观察发现s1为s子集
所以可以三进制表示:0表示都不在,1表示在s不在s1,2表示既在s又在s1
然后可以AC此题
[代码待补]
【错解】
woc提高考树剖?还没法维护?
骗分,放弃
WA10
【正解】
一个结论:树上两条路径有交集,当且仅当其中一条路径的LCA在另一条路径上
然后就转化为:
单点修改,路径查值
路径修改,单点查值
然后直接上树链……什么?被卡了?
考虑路径可以转换为4个点到根路径,做个类似于树上前缀和的玩意
然后直接上树剖
因为是单点查值,到根路径对其有影响当且仅当在其子树上
然后成了子树 树状数组维护dfs序即可
[代码待补]