FFT_应用和例题
卷积
现有两个定义在 N 上的函数 \(f(n),g(n)\),定义 \(f\) 和 \(g\) 的卷积(convolution)为 \(f \otimes g\)
\]
示意图: from http://blog.miskcoo.com/2015/04/polynomial-multiplication-and-fast-fourier-transform#i-17

考虑两多项式 \(A, B\) 的乘积 \(C\), \(c(x) = \sum_{i=0}^{x} a(i) \cdot b(x - i)\)
系数记为卷积形式
于是计算卷积 \((f \otimes g)(n)\) 就可以把 \(f, g\) 的值直接作为系数写成两个多项式, 然后 FFT 计算多项式乘积, 得到的系数的前 \(n\) 项即为所求
BZOJ3527[ZJOI2014]力
题意:
给出 \(n\) 个数 \(q_i\) ,给出 \(F_j\) 的定义如下:
\]
令 \(E_j = F_j / q_j\) , 求 \(E_j\)
Sol:
因为知道是卷积的例题了, 所以想着把这个式子往卷积的方向靠
E_j = \sum_{i < j}\frac{q_i}{(i - j) ^ 2} - \sum_{i > j}\frac{q_i}{(i - j) ^ 2}
\end{aligned}
\]
考虑分母当做系数, 再考虑下标和为 \(j\) , 写成这样
E_j = \sum_{i < j}\frac{1}{(j - i) ^ 2}q_i - \sum_{i > j}\frac{1}{(j - i) ^ 2}q_i
\end{aligned}
\]
一开始想把两个一起做, 发现写不出两个函数, 于是考虑分开做
显然 \(\sum_{i < j}\frac{1}{(j - i) ^ 2}q_i\) 就是 \(f(n) = q_n\) 和 \(g(n) = \frac{1}{n^2}\) 的卷积
然后后面一项同理, 把 \(f(n)\) 翻转一下即可
然后跑 FFT
double ans[MAXN], q[MAXN];
/*
20191212
0859~0922~0939
BZOJ3527 FFT
*/
int main()
{
scanf("%d", &lena);
for (int i = 0; i < lena; ++ i)
{
scanf("%lf", &a[i].x); q[lena - 1 - i] = a[i].x;
b[i].x = (i == 0 ? 0.0 : 1.0 / i / i);
}
while ((1 << dgt) < lena * 2) ++ dgt;
n = 1 << dgt;
init(n, dgt);
FFT(b, n ,1);
FFT(a, n, 1);
for (int i = 0; i < n; ++ i) a[i] = a[i] * b[i];
FFT(a, n, -1);
for (int i = 0; i < lena; ++ i) ans[i] += a[i].x / n;
for (int i = 0; i < n; ++ i) a[i].x = q[i], a[i].y = 0;
FFT(a, n, 1);
for (int i = 0; i < n; ++ i) a[i] = a[i] * b[i];
FFT(a, n, -1);
for (int i = 0; i < lena; ++ i) ans[i] -= a[lena - 1 - i].x / n;
for (int i = 0; i < lena; ++ i) printf("%.3f\n", ans[i]);
return 0;
}
/*
3
1 2 3
*/
字符串匹配
给定两个字符串 \(A, B, |A| \ge |B|\), 用 \(B\) 取匹配 \(A\),
那么可以发现对应位置的差恒定, 要转化成卷积形式, 可以将 \(B\) 翻转, 于是就可以构造卷积了
BZOJ4892[Tjoi2017]DNA
题意:
多测, 给两个字符串 \(A, B\), 字符集是 ACGT, 匹配的定义是相差不超过 3 个字符, 求 \(B\) 在 \(A\) 中匹配的次数
\(n \le 1e5, T \le 10\)
Sol:
翻转 \(B\)
一开始构造了这样的 : \(ans_i = \sum_{j=0}^i (a_j - b_{i - j}) ^ 2 \cdot a_j \cdot b_{i-j}\)
然后单独计算 \(B\) 中四个字符的贡献, 36 个 FFT
其实不需要这么套路, 反正都单独计算了, 可以更加钦点一点
\(ans_i = \sum_{j=0}^i a_j \cdot b_{i-j}\)
\(B\) 中是枚举的字符就 1 否则 0 , \(A\) 中相反
这样得到的某一位卷积就是不一样的个数
int ans[MAXN];
void read(int * a, int & len)
{
scanf("%s", tmp);
len = strlen(tmp);
for (int i = 0; i < len; ++ i)
if (tmp[i] == 'A') a[i] = 0;
else if (tmp[i] == 'G') a[i] = 1;
else if (tmp[i] == 'C') a[i] = 2;
else a[i] = 3;
}
int fpow(int a, int b)
{
int ret = 1;
for (int i = 1; i <= b; ++ i) ret *= a;
return ret;
}
void solve(int x)
{
for (int i = 0; i < n; ++ i) ca[i] = cb[i] = 0;
for (int i = 0; i < lena; ++ i)
{
if (sa[i] == x) ca[i] = 0;
else ca[i] = 1;
}
for (int i = 0; i < lenb; ++ i)
{
if (sb[i] == x) cb[i] = 1;
else cb[i] = 0;
}
for (int i = 0; i < n; ++ i)
a[i] = (Cpx) { ca[i], 0 }, b[i] = (Cpx) { cb[i], 0 };
FFT(a, n, 1); FFT(b, n, 1);
for (int i = 0; i < n; ++ i) a[i] = a[i] * b[i];
FFT(a, n, -1);
for (int i = 0; i < n; ++ i)
ans[i] += (int)(a[i].x / n + 0.5);
}
int main()
{
int T;
scanf("%d", &T);
while (T --)
{
read(sa, lena);
read(sb, lenb);
reverse(sb + 0, sb + lenb);
n = 1, dgt = 0;
while (n < lena + lenb) n <<= 1, ++ dgt;
init(n, dgt);
for (int i = 0; i < n; ++ i) ans[i] = 0;
for (int i = 0; i < 4; ++ i) solve(i);
int cnt = 0;
for (int i = lenb - 1; i < lena; ++ i)
if (ans[i] <= 3) ++ cnt;
printf("%d\n", cnt);
}
return 0;
}
/*
2
ATCGCCCTA
CTTCA
ACGT
GTCA
*/
FFT_应用和例题的更多相关文章
- BIT 树状数组 详解 及 例题
(一)树状数组的概念 如果给定一个数组,要你求里面所有数的和,一般都会想到累加.但是当那个数组很大的时候,累加就显得太耗时了,时间复杂度为O(n),并且采用累加的方法还有一个局限,那就是,当修改掉数组 ...
- STL模板中的map的使用与例题
最近的计分赛,记得自己的都只是过了两题.遇到了两次map,自己在寒假看了一点的map,只知道在字符串匹配的时候可以用的到.但是自己对map的使用还是不够熟练使用,这回在第一次和第二次的计分赛中都遇到可 ...
- C语言经典例题100
C语言经典例题100 来源 http://www.fishc.com 适合初学者 ----------------------------------------------------------- ...
- 图的全局最小割的Stoer-Wagner算法及例题
Stoer-Wagner算法基本思想:如果能求出图中某两个顶点之间的最小割,更新答案后合并这两个顶点继续求最小割,到最后就得到答案. 算法步骤: --------------------------- ...
- lca入门———树上倍增法(博文内含例题)
倍增求LCA: father[i][j]表示节点i往上跳2^j次后的节点 可以转移为 father[i][j]=father[father[i][j-1]][j-1] 整体思路: 先比较两个点的深度, ...
- acm常见算法及例题
转自:http://blog.csdn.net/hengjie2009/article/details/7540135 acm常见算法及例题 初期:一.基本算法: (1)枚举. (poj17 ...
- [LeetCode] “全排列”问题系列(二) - 基于全排列本身的问题,例题: Next Permutation , Permutation Sequence
一.开篇 既上一篇<交换法生成全排列及其应用> 后,这里讲的是基于全排列 (Permutation)本身的一些问题,包括:求下一个全排列(Next Permutation):求指定位置的全 ...
- C语言中的经典例题用javascript怎么解?(一)
C语言中的经典例题用javascript怎么解?(一) 一.1+2+3+……+100=? <script type="text/javascript"> ...
- 数据库留言板例题:session和cookie区别
session和cookie区别: <?php session_start(); //session_start();必须写在所有的php代码前边 ?> <!DOCTYPE html ...
随机推荐
- 剑指Offer-30.连续子数组的最大和(C++/Java)
题目: HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学.今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决.但是,如果向量中 ...
- Python gc
Python gc Python gc 模块提供垃圾回收器的接口 关于 Python 垃圾回收 <- 点击查看 官方文档:https://docs.python.org/3/library/gc ...
- Mysql如何在删库后可以不用跑路
我一直在想,地球上这么多程序员,应该有很多人在团队做项目的时候,出过很大的错误,比如说不小心删了库,活动福利字段多写了个零导致全服务器玩家领到数倍奖励,听了沙雕群友的话执行rm -rf命令. 记得有一 ...
- Gitlab安装过程
sudo yum install -y curl policycoreutils-pythonopenssh-server sudo systemctl enable sshd sudo system ...
- pytorch固定部分参数
pytorch固定部分参数 不用梯度 如果是Variable,则可以初始化时指定 j = Variable(torch.randn(5,5), requires_grad=True) 但是如果是m = ...
- 【Linux命令】nohup命令用法
nohup命令用法 当我们想将某个脚本或程序运行在后台的时候.我们一般会在程序或脚本后面添加 & 字符来表示在后台运行,但使用& 运行在后台,当我们将shell窗口关闭时,该脚本或程序 ...
- Appium+java ---- Intellij IDEA +genymotion安装配置
引用文章:https://www.cnblogs.com/kaola8023/p/8442686.html Intellij IDEA 中配置Android SDK File-Project Stru ...
- node 连接 mysql 数据库三种方法------笔记
一.mysql库 文档:https://github.com/mysqljs/mysql mysql有三种创建连接方式 1.createConnection 使用时需要对连接的创建.断开进行管理 2. ...
- route 相关设置
Debian系统 查看路由表: root@debian:~# ip route default via 192.168.6.1 dev enp4s0 10.0.0.0/24 dev br0 proto ...
- MySQL(10)---自定义函数
MySQL(10)---自定义函数 之前讲过存储过程,存储过程和自定义函数还是非常相似的,其它的可以认为和存储过程是一样的,比如含义,优点都可以按存储过程的优点来理解. 存储过程相关博客: 1.MyS ...