退役前做题记录
rt,做完就退役
ICPC2018-2019 shenyang M
每个位置的生成函数是\({1-x^{b_i(a_i+1)}\over 1-x^{b_i}}\),可以拆成一个完全背包和一个\(01\)背包,类似的每个位置的逆\({1-x^{b_i}\over 1-x^{b_i(a_i+1)}}\)也可以,那么可以预处理出前缀背包和前缀背包的逆,每一次\(O(c)\)回答询问就行了
LOJ#2271
首先考虑暴力,相当于每次看看能不能把\({1\over 1-x^i}\)卷上去,如果前面都已经确定了,那么答案多项式只会被这一项影响了,所以\({1\over 1-x^i}\)要不要卷上去一定是被当前多项式和答案多项式确定的,所以\(S\)事实上是唯一确定的
记答案多项式为\(B(x)\),\(S\)的多项式为\(A(x)\),其中\(A\)的每个系数为\(0\)或\(1\),那么有
即
我们从\(1\)到\(n\)依次考虑\(a_i=0\)还是\(1\),那么肯定已经被唯一确定了,对之后的有影响的项是\(O({n\over i})\)项,所以总复杂度还是\(O(n\log n)\)
LOJ#2552
怎么老是犯sb错误啊
暴力维护\(f_{i,j}\)表示第\(i\)个人还有\(j\)滴血的概率,每次询问时暴力把所有人卷起来,然后对每个人退背包就行了,退背包手动模拟多项式除法就可以做到单次\(O(n)\)了
LOJ#556
类似LOJ#2271画一下柿子就行了
LOJ#565
首先打个表发现答案与操作顺序无关,再手玩一下发现如果操作的数已经确定了,那么某一位被更改的次数就是自己变的次数以及被后面进位的次数之和,写成伪代码就是
int calc(){
R int ret=0;
fp(i,0,n)g[i]=f[i];g[n+1]=0;
fp(i,0,n)upd(ret,g[i]),g[i+1]+=g[i]>>1;
for(R int i=n+1;g[i];++i)upd(ret,g[i]),g[i+1]=g[i]>>1;
return ret;
}
其中\(f_i\)表示第\(i\)位被选择的次数,这样我们可以写出一个\(O(n^2)\)的做法,也就是设\(f_{i,j}\)表示考虑到第\(i\)位,且\(g_i=j\)的概率,转移即可
冷静分析一波,发现一个\(g_i\)最多只会影响后面\(O(\log n)\)个位置,也就是说如果我们把\(f_i\)写成生成函数,那么所有多项式的次数之和是\(O(n\log n)\)级别的,那么对于每个位置,分治\(NTT\)算出原来的多项式,然后从前往后多项式乘法即可,总复杂度\(O(n\log^2n)\)
LOJ#3106
居然连容斥都想不到,可以退役了
首先容斥\(abcd\)的个数,然后枚举\(a,b,c,d\)的个数之后用个多项式系数计算一下方案数就行了。发现\(d\)的个数不用枚举,再发现合法的\(c\)的个数是一个区间,预处理一下就好了,总复杂度\(O(n^3)\),或者直接把四个多项式卷积起来也行