玄学算法/精彩DS总结 Ludi

teafrogsf

2019-04-12 12:33:57

Personal

## $58.Polynomial\ Multipoint\ Evaluation\&Faster\ Interpolation$ 本来这个内容是应该在总结$slide$里的,但因为太麻烦了所以暂时先放这儿。如果我大学搞$ACM$了就把它放到$slide$里吧。 ### $1.$多点求值 多项式多点求值就是给定你多项式$F$和$x_1,\cdots,x_n$,求出它们的值。这里的算法是$O(n\log^2n)$的。 我们考虑直接计算的时间复杂度显然是$O(ndeg(F))$的,所以无论如何我们计算的时候要减少$deg$。 那么我们进行分治,假设现在的多项式是$F_0$,考虑把点集划分为$[x_l,x_{mid}],[x_{mid+1},x_r]$两个部分,然后我们需要减少多项式的度数,最好能减少到$\frac{deg(F_0)}2$。 我们可以构造 $$P_l=\sum_{i=l}^{mid}(x-x_i),P_r=\sum_{i=mid+1}^r(x-x_i)$$ ,这样我们可以发现,当$x\in[l,mid]$里的$x$时,$P_l=0$,右边同理$P_r=0$。 那样也就是说 $$F_l\equiv F_0\pmod{P_l},F_r\equiv F_0\pmod{P_r}$$ 于是我们可以直接对$F_0$取模,就得到了两个部分。 然后当$l=r$的时候,多项式就只有常数项了,那就是这个点的值。 显然每次我们会让度数$\div 2$,时间复杂度$T(n)=2T(\frac n2)+O(n\log n)=O(n\log^2 n)$(此处我们默认$n,deg$同阶)。 ### $2.$快速插值 其实我一直很想吐槽这个名字,插值就插值你还要加个快速,仿佛就是为了与多点求值对称一样。 我们考虑拉格朗日插值的过程 $$F(x)=\sum_{i=1}^ny_i\frac{\prod_{j\neq i}(x-x_j)}{\prod_{j\neq i}(x_i-x_j)}$$ $$=\sum_{i=1}^n\frac{y_i}{\prod_{j\neq i}(x_i-x_j)}\prod_{j\neq i}(x-x_j)$$ 我们先考虑左边那一块的计算。 由于$y_i$是常数,我们只需要计算分母。我们可以搞一个多项式 $$G(x)=\prod_{j=1}^n(x-x_j)$$ ,然后分母就是$\frac{G(x_i)}{x-x_i}$。 根据洛必达法则,这个东西$=G'(x_i)$。我们对$G$求导后,多点求值即可。 接下来我们考虑我们已经求得了$[l,mid],[mid+1,r]$的多项式$F_l,F_r$,怎么求$F$。 $$\begin{aligned}F(x)&=\sum_{i=1}^n\frac{y_i}{\prod_{j\neq i}(x_i-x_j)}\prod_{j\neq i}(x-x_j)\\&=\sum_{i=l}^{mid}\frac{y_i}{G'(x_i)}\prod_{j\neq i}(x-x_j)+\sum_{i=mid+1}^r\frac{y_i}{G'(x_i)}\prod_{j\neq i}(x-x_j)\\&=\sum_{i=l}^{mid}\frac{y_i}{G'(x_i)}\prod_{j=l,j\neq i}^{mid}(x-x_j)\prod_{j=mid+1}^r(x-x_j)+\sum_{i=mid+1}^r\frac{y_i}{G'(x_i)}\prod_{j=mid+1,j\neq i}^{r}(x-x_j)\prod_{j=l}^{mid}(x-x_j)\\&=F_l\prod_{j=mid+1}^r(x-x_j)+F_r\prod_{j=l}^{mid}(x-x_j)\end{aligned}$$ 连续乘积显然可以分治$FFT$预处理出来,于是就做完了。 时间复杂度是$O(n\log^2n)$的,但我觉得它的常数不比线性递推小$\cdots\cdots$ ## $59?.Min\_26\ Sieve$ 在讲$Min\_26$筛之前,我们先搞明白$Min\_25$筛的本质是什么。 首先,狭义的$Min\_25$筛指的是在之前已经提到过的过程,而广义的$Min\_25$筛实际上是指的两步过程:第一步先把所有质数部分的贡献算出来,第二步计算对于每一个$\lfloor\frac ni\rfloor$位置的真正前缀和,这一部分需要用到之前的质数贡献,通过枚举当前质因子的次数进行筛除。一般情况下,它的时间复杂度为$O(\frac{n^\frac34}{\log n}+n^{1-\epsilon})$,大约在$n=10^{11}$时能在一秒内筛完。 ## $60..vimrc$ ~~的确有两个点。~~ 前面部分压行之后应该一共9行。 ``` set nocp set go= syntax on set ruler set guifont=Consolas:h16 set guioptions+=b set guioptions+=r color molokai set nu set mouse=a set backspace=eol,indent,start set tabstop=4 set shiftwidth=4 set softtabstop=4 set cindent set autoindent set smartindent set autoread autowrite autochdir set cursorline set cursorcolumn set clipboard=unnamed set fileencodings=utf-8,ucs-bom,gb18030,gbk,gb2312,cp936 set termencoding=utf-8 set encoding=utf-8 map<F6> :!python %<CR> map<F7> :27vsp %<.in<CR>:sp %<.out<CR> map<F9> :!g++ % -o %< -lm -std=c++11 -Wl,-stack=1000000000 -Wshadow -Wextra -Wall -O2 && %< <CR> map<F8> :!g++ % -o %< -lm -std=c++11 && %< <CR> map<F1> :call libcallnr("vimtweak.dll","SetAlpha",180)<CR> map<F2> :call libcallnr("vimtweak.dll","SetAlpha",0)<CR> map<F3> :call libcallnr("vimtweak.dll","SetAlpha",88)<CR> map<F4> :call libcallnr("vimtweak.dll","SetAlpha",255)<CR> map<F5> :call libcallnr("vimtweak.dll","SetAlpha",1)<CR> source $VIMRUNTIME/vimrc_example.vim source $VIMRUNTIME/mswin.vim behave mswin set diffexpr=MyDiff() function MyDiff() let opt = '-a --binary ' if &diffopt =~ 'icase' | let opt = opt . '-i ' | endif if &diffopt =~ 'iwhite' | let opt = opt . '-b ' | endif let arg1 = v:fname_in if arg1 =~ ' ' | let arg1 = '"' . arg1 . '"' | endif let arg2 = v:fname_new if arg2 =~ ' ' | let arg2 = '"' . arg2 . '"' | endif let arg3 = v:fname_out if arg3 =~ ' ' | let arg3 = '"' . arg3 . '"' | endif if $VIMRUNTIME =~ ' ' if &sh =~ '\<cmd' if empty(&shellxquote) let l:shxq_sav = '' set shellxquote& endif let cmd = '"' . $VIMRUNTIME . '\diff"' else let cmd = substitute($VIMRUNTIME, ' ', '" ', '') . '\diff"' endif else let cmd = $VIMRUNTIME . '\diff' endif silent execute '!' . cmd . ' ' . opt . arg1 . ' ' . arg2 . ' > ' . arg3 if exists('l:shxq_sav') let &shellxquote=l:shxq_sav endif endfunction ``` ## $61.IO$ ```cpp namespace IO { const unsigned int bufsize=1<<16,outsize=1<<24; static char ch[bufsize],*S=ch,*T=ch; inline char getc() {return ((S==T)&&(T=(S=ch)+fread(ch,1,bufsize,stdin),S==T)?0:*S++);} static char Out[outsize],*nowp=Out; inline void flush(){fwrite(Out,1,nowp-Out,stdout);nowp=Out;} template<typename T> void read(T &x) { char c=getc();x=0; for(;!isdigit(c);c=getc()); for(;isdigit(c);x=(x<<1)+(x<<3)+(c^'0'),c=getc()); } template<typename T> void write(T x,char c='\n') { if(!x)*nowp++='0'; if(x<0)*nowp++='-',x=-x; static unsigned int stk[50],tp=0; for(;x;x/=10)stk[++tp]=x%10; for(;tp;*nowp++=stk[tp--]^'0');*nowp++=c; } } ```