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 ...
随机推荐
- 使用docker运行springboot项目
本文主要讲的是使用docker运行springboot项目 获取一个springboot项目 这里我没有重新构建,用的之前写的一个项目,直接从github上下载下来,地址:https://github ...
- WPF 动态列(DataGridTemplateColumn) 绑定数据 (自定义控件)对象绑定
原文:WPF 动态列(DataGridTemplateColumn) 绑定数据 (自定义控件)对象绑定 WPF 动态列(DataGridTemplateColumn) 绑定数据 (自定义控件) 上面的 ...
- PHP面试题大全(值得收藏)
PHP进阶.面试:文档.视频资源点击免费获取 一 .PHP基础部分 1.PHP语言的一大优势是跨平台,什么是跨平台? PHP的运行环境最优搭配为Apache+MySQL+PHP,此运行环境可以在不同操 ...
- 前端优化,包括css,jss,img,cookie
前端优化,来自某懒观看麦子学院视频的笔记. 尽可能减少HTTP的请求数 使用CDN 添加Expirs头,或者Cache-control Gzip组件压缩文件内容 将CSS放在页面上方 将脚本放到页面下 ...
- Springboot 打包自带启动脚本
一直以来,我都是 gradlew build java -jar xxx.jar 来启动springboot项目的.今天突然发现,springboot自动封装了一个bootJar的任务脚本. demo ...
- css文本省略号
这里记录下如何用CSS实现单行.多行文本溢出容器的时候用省略号代替溢出部分. 单行文本溢出容器时显示省略号的CSS实现方法 /* 规定当内容溢出元素框(容器)时隐藏 */ overflow: hidd ...
- python-3.8.0 新特性之赋值表达式
[python-3.8.0 新特性之赋值表达式] 赋值表达式的语法是这样的“ name := expression ”,形式上看和赋值语句 “ = ” 差不多,就作用上来看也雷同.也就是说 “:=” ...
- 【UOJ#310】【UNR#2】黎明前的巧克力(FWT)
[UOJ#310][UNR#2]黎明前的巧克力(FWT) 题面 UOJ 题解 把问题转化一下,变成有多少个异或和为\(0\)的集合,然后这个集合任意拆分就是答案,所以对于一个大小为\(s\)的集合,其 ...
- java高并发系列 - 第11天:线程中断的几种方式
java高并发系列第11篇文章. 本文主要探讨一下中断线程的几种方式. 通过一个变量控制线程中断 代码: package com.itsoku.chat05; import java.util.con ...
- css 行内水平均等排布方式
<div class="justify"> <span>测试1</span> <span>测试2</span> < ...