卷积

现有两个定义在 N 上的函数 \(f(n),g(n)\),定义 \(f\) 和 \(g\) 的卷积(convolution)为 \(f \otimes g\)

\[(f \otimes g)(n) = \sum_{i=0}^n f(i)g(n-i)
\]

示意图: 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\) 的定义如下:

\[F_j = \sum_{i < j}\frac{q_i q_j}{(i - j) ^ 2} - \sum_{i > j}\frac{q_i q_j}{(i - j) ^ 2}
\]

令 \(E_j = F_j / q_j\) , 求 \(E_j\)

Sol:

因为知道是卷积的例题了, 所以想着把这个式子往卷积的方向靠

\[\begin{aligned}
E_j = \sum_{i < j}\frac{q_i}{(i - j) ^ 2} - \sum_{i > j}\frac{q_i}{(i - j) ^ 2}
\end{aligned}
\]

考虑分母当做系数, 再考虑下标和为 \(j\) , 写成这样

\[\begin{aligned}
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_应用和例题的更多相关文章

  1. BIT 树状数组 详解 及 例题

    (一)树状数组的概念 如果给定一个数组,要你求里面所有数的和,一般都会想到累加.但是当那个数组很大的时候,累加就显得太耗时了,时间复杂度为O(n),并且采用累加的方法还有一个局限,那就是,当修改掉数组 ...

  2. STL模板中的map的使用与例题

    最近的计分赛,记得自己的都只是过了两题.遇到了两次map,自己在寒假看了一点的map,只知道在字符串匹配的时候可以用的到.但是自己对map的使用还是不够熟练使用,这回在第一次和第二次的计分赛中都遇到可 ...

  3. C语言经典例题100

    C语言经典例题100 来源 http://www.fishc.com 适合初学者 ----------------------------------------------------------- ...

  4. 图的全局最小割的Stoer-Wagner算法及例题

    Stoer-Wagner算法基本思想:如果能求出图中某两个顶点之间的最小割,更新答案后合并这两个顶点继续求最小割,到最后就得到答案. 算法步骤: --------------------------- ...

  5. lca入门———树上倍增法(博文内含例题)

    倍增求LCA: father[i][j]表示节点i往上跳2^j次后的节点 可以转移为 father[i][j]=father[father[i][j-1]][j-1] 整体思路: 先比较两个点的深度, ...

  6. acm常见算法及例题

    转自:http://blog.csdn.net/hengjie2009/article/details/7540135 acm常见算法及例题  初期:一.基本算法:     (1)枚举. (poj17 ...

  7. [LeetCode] “全排列”问题系列(二) - 基于全排列本身的问题,例题: Next Permutation , Permutation Sequence

    一.开篇 既上一篇<交换法生成全排列及其应用> 后,这里讲的是基于全排列 (Permutation)本身的一些问题,包括:求下一个全排列(Next Permutation):求指定位置的全 ...

  8. C语言中的经典例题用javascript怎么解?(一)

    C语言中的经典例题用javascript怎么解?(一) 一.1+2+3+……+100=?        <script type="text/javascript">  ...

  9. 数据库留言板例题:session和cookie区别

    session和cookie区别: <?php session_start(); //session_start();必须写在所有的php代码前边 ?> <!DOCTYPE html ...

随机推荐

  1. SpringBoot(二十一)_使用xml

    springboot使用xml 虽然springboot不提倡用xml,但是我们有可能也是会用到的 代码示例 1.创建一个配置文件在resources下,如下图所示 2.设置配置类 @Configur ...

  2. fis3打包中的一些注意事项

    1.在html文件中,如果在标签的style属性内添加路径,fis不会识别改路径并打包,如 2.fis主要针对静态文件进行打包.对其他文件打包会出现一些问题. 比如jsp页面.下面的例子script. ...

  3. 新手入门:python的pip安装(二)

    pip的安装以及使用pip安装包 —–安装python的时候勾选了下载pip,不知道为什么没下载.然后就偷懒想着需要哪个包再单独去下载就好了,然后!!!每个包都会出点小问题,导致我这个初学者有三天不想 ...

  4. Mybatis关联查询之一

    MyBatis的关联查询之一对多,多对一 在关系型数据库中,我们经常要处理一对多,多对一和多对多的关系. 一对多,多对一 一.entity 实体类 public class SmbmsRole { p ...

  5. 【CF241E】Flights(差分约束)

    [CF241E]Flights(差分约束) 题面 CF 有\(n\)个点\(m\)条边,要求给每条边赋一个\(1\)或\(2\)的边权,判断能否使得每一条\(1\)到\(n\)的路径的权值和都相等,如 ...

  6. C# Task ContinueWith

    static void Main(string[] args) { Task firstTask = Task.Run(() => { PrintPlus(); }); Task secondT ...

  7. Python爬取上交所一年大盘数据

    前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者: 半个码农2018 PS:如有需要Python学习资料的小伙伴可以加点 ...

  8. 数据类型和特殊类型-C#

    参考地址:https://blog.csdn.net/qiaoquan3/article/details/51380992 1.集合set:纯粹的数据集合 2.线性结构:一对一的,数组 3.树形结构: ...

  9. iOS安全攻防(一):Hack必备的命令与工具

    转自:http://blog.csdn.net/yiyaaixuexi/article/details/8288077 你的应用正在被其他对手反向工程.跟踪和操作!你的应用是否依旧裸奔豪不防御? 郑重 ...

  10. NSCach 的知识小记

    (1)NSCach 可以设置最大缓存数据的数量,如果超出该限制那么内部会自动开启一个回收过程把最先存储的数据删除 (2)NSCach 可以设置代理,<NSCachDelegate>,可以监 ...