快速傅里叶(FFT)题表

前言

最近终于学了FFT
以前被scy逼着学过一次没有学会,这次终于好一点了
在这里大致放一下一些FFT的题目

题表

uoj34
多项式乘法,这个估计是大多数人的入门题了吧

codevs3123
大整数高精度,其实和上面那题是差不多的

bzoj3527
化一下式子,然后两个FFT就可以得出答案了

bzoj3771
这题的话,也不是很难
你只需要分别讨论选择一个,选择两个,选择三个,然后求方案的话,就先用FFT求出构成i有多少种方案,然后去掉不合法,去掉一些重复算的就可以了。。大概想一想就能想出来了

bzoj2194
这题很明显,每个值就是
b[j]a[k+j] b [ j ] ∗ a [ k + j ] 的总和
发现不是很好做
我们发现,如果将a数组反过来,式子就会变成
b[j]a[n(k+j)] b [ j ] ∗ a [ n − ( k + j ) ]
这个样的话两个坐标里面的和就是 nk n − k
其实这个就是很明显就是卷积的形式了,然后就FFT乱搞一下就可以了

bzoj3513
先搞出用两条线段可以弄出的长度方案,去下重,暴力算一算就好了,当模板题练一下就好了

bzoj4259
bzoj4503
这两题其实是一样的,然后我就没有想出来了,于是就只能%题解了

首先有一个 O(26nlogn) O ( 26 n l o g n ) 的做法
先是吧T反过来
就是按位处理,比如说字母a,那么就在S里面所有a标一个1,T所有a也标一个1,然后FFT一下,就可以求出来每一位的匹配
然后别的也一样
最后看一下某一位的值是不是T的长度就可以了
当然这样肯定是会T的

于是我们需要换一种方法 题解
快速傅里叶(FFT)题表_第1张图片

bzoj3509
这题想了我差不多半个多小时,最后发现其实是一个很简单的题
这题转换成,在左边选择一个数,右边选择一个数,和为自身的两倍,问有多少种方案
这个是十分容易想到的
然后我们对于一个数,就可以将两边的数FFT一下?
于是就得到了一个 O(n2logn) O ( n 2 l o g n ) 的做法
这个做法显然不够优秀啊
因为我们一次FFT得到有用的信息实在是太少了,很浪费
于是我们考虑一次FFT做出更多的贡献
就是我们把序列分块,一个块里面的数,两侧的FFT结果明显是可以共用的
于是乎,就只剩下块里面的影响没有处理了,这个暴力处理一下就好了啊!
然后就可以搞过去了,感觉还是蛮简单的
时间复杂度,FFT会用块的个数次,然后每个点,算出答案的代价就是块的大小
那不就很简单了嘛,你就平衡一下块的大小,然后就是一个很简单的题了!

bzoj3160
这题还是蛮简单的吧。。
如果两个为i,j相等,那么他对 (i+j)/2 ( i + j ) / 2 这个地方,可行方案a++
然后每一个点对答案的贡献就是 2a1 2 a − 1
然后其实你可以吧 (i+j)/2 ( i + j ) / 2 /2 / 2 给删掉
那么不就是卷积的形式了吗?
至于后面怎么搞,五花八门啦
然后最后连续的就用manacher扫一下就出来了

bzoj4332
感觉我最近效率很低啊,每天来到竞赛室都很困,然后就想睡觉了
这题的裸DP还是蛮好弄的吧。。
就是 f[i][j] f [ i ] [ j ] 表示一下就可以了
然后这个的复杂度很明显是 O(m2) O ( m 2 )
然后我们考虑进行倍增,如果我们没有”所有没有糖的人都要在最后连续的一段”,这个限制,那么我们就直接用FFT倍增转移就可以了
现在多了一个限制,就不好这么做了
但是没有关系,我们可以搞多一个数组 g g
表示在当前的小朋友个数里面,分了 i i 个糖果,并且一定要有一段后缀 0 0 的答案和
然后 f f 数组表示,我们不可以有后缀 0 0 的答案和
至于转移,f的就很好弄啦
然后 g g 的话,就是前面一半是 f f 的,后面一半是 g g 的并起来
也就是 g[i]=g[ik]f[k] g [ i ] = g [ i − k ] ∗ f [ k ]
当然f是覆盖的,g是累加的(这个很重要,我开始想成g是覆盖的,就一直没有弄出来)
因为前面一半的小朋友没有糖的情况是前面处理的嘛
然后就做完了

bzoj4827
就用一个水题来暂时吧这个专题告一段落吧。。
这题的话,你就把a串倍长,b串反串
然后随便化下式子,就可以做出来了
然后考虑到m很小,于是你就暴力地枚举要加多少
注意的是,这里加其实等于另外一个串减
所以你只需要做一次就可以了,就是枚举某个串加多少,范围是 mn − m 到 n
时间复杂度 O(nlogn) O ( n l o g n )

你可能感兴趣的:(FFT,题表/复习小结)