优化高精度乘法
朴素的高精度乘法的复杂度是$O(n^2)$的
应用FFT可以做到$O(n\log n)$
我们可以把数写成多项式的形式,例如:
$1523=3\times 10^0 + 2 \times 10^1+5\times 10^2+1\times 10^3$
这样两数相乘实际上就是多项式相乘,上FFT就行了
|
|
计算卷积
形如$C_k=\sum_{j=0}^{k} A_j B_{k-j}$的式子叫作卷积
利用FFT可以快速求出卷积
- 【bzoj2194】传送门
我们把数组来回拧一拧,就成了卷积形式,然后上FFT
|
|
统计和为某值的数的对数
例一
【HDU4609】3-idiots
题目大意:给出n个正整数,求从中任选3个数(下标不重复),求以这三个数为长度的边能构成三角形的概率。
分析:令a[i]表示数i有多少个,对a求一遍卷积就可以得到任选两个数,和为x的方案数,这里注意要去一下重
由于三角形两边之和大于第三边,我们就能先用前缀和算出组不成三角形的方案,然后减一下就好了
|
|
例二
【SPOJ-TSUM】Triple Sums
题目大意:给出n(n<=40000)个整数(绝对值<=20000),对任意三个下标不同的数求和,问和为-60000到60000的数对各有多少个。
分析:这次变成了三个,唯一的不同点在于去重,用容斥原理搞一搞就行了
|
|
例三
【bzoj3771】Triple
这道题就是把例一和例二加起来
|
|
例四
【uva12633】Super Rooks on Chessboard
题目大意:一个n*m的地图上有一些格子里有骑士,每个骑士可以攻击到它所在行,所在列以及所在的从左上到右下的对角线的所有格子,问有多少格子没被任何一个骑士攻击到。
数据范围:n,m<=50000,骑士数<=50000。
分析:如果以左下角为原点,会发现一条对角线上的(x+y)坐标是相同的,且任意两条对角线的(x+y)不同。由此我们就可以联想到卷积了。
设两个数组a,b,a[i]表示第i行是否被占领,b[i]表示第i列是否被占领,是的话值为0,否则值为1。
两个数组求个卷积,把没被攻击的第(x+y)项系数统计出来就行了。
|
|
解决01串匹配问题
例一
【bzoj4503】两个串
分析:定义两个长度相同的子串距离为$\sum (a_i-b_i)^2 b_i$
通配符置为0,这样就可以保证距离为0的两个串可以匹配,然后把s2反转一下求卷积就可以了。
|
|
优化dp
例一
【ZOJ3874】Permutation Graph
题目大意:给出一个1-n的排列,对于任意一个逆序对,在这两个位置连一条无向边,给你最终每个连通块的元素,求有多少种排列方案。
分析:很容易发现,每个连通块的元素一定是连续的,并且连通块之间顺序是固定的。那么我们可以预处理出长度为i的连通块的方案数,求解复杂度就可以和输入同阶了。
令dp[i]表示长度为i的连通块方案数。
Dp[i]=i!−∑𝑘!∗𝑑𝑝[i-k] (k=1…i),dp[0]=0.
|
|
例二
【HDU5322】Hope
题目大意:给出一个排列,每个点向它右面离它最近的且比它大的点连无向边,每个连通块的价值为这个连通块大小的平方,每个排列的价值为所有连通块之积。求n个数的所有排列的价值之和。
解析:考虑到放完前i个数再放i+1,不管i+1放在哪里,i+1之前的数形成了一个连通块,且对之后的没有影响。
于是可以列出方程
Dp[i]=sigmak(dp[i-k]k^2C(i-1,k-1)*(k-1)!)
Dp[i]/(i-1)!=sigmak(dp[i-k]/(i-k)!*k^2)
然后就可以CDQ分治做了
|
|
和数据结构套在一起
例一(分块FFT)
【bzoj3509】COUNTARI
考虑暴力做法,枚举中间元素,两边暴力FFT,时间复杂度为$O(n^2logn)$。
然而我们可以优化一些东西。
我们把序列分块,把有至少两个数在同一个块内的(i,j,k)暴力求出来,设块大小是B,n*B的,B大概要设到2000左右。然后对于三个点都在不同块的再暴力FFT就好了。
|
|