FFT学习小结

news/2025/10/18 23:46:44/文章来源:https://www.cnblogs.com/ganking/p/19150322

关键词

多项式乘法,系数表示,点值表示,单位根

FFT基本思路

  1. 系数表示->点值多项式
  2. 点值下直接相乘,时间复杂度O(n)
  3. 点值多项式->系数表示

系数表示->点值多项式

  • 分治思想,奇偶分开,单位根
  • 假定\(f(x)=\sum_{i=0}^{n-1}a_ix^i\),其中n为2的幂次
  • 对于一个有n个系数的多项式,点值表示需要n个不同的点,
  • 那么考虑使用单位根\(x^n=1\)的n个解(\(\omega_{n}^0,\omega_{n}^1...\omega_{n}^{n-1}\)),来作为这n个点
  • 那么我们只需求出\(f(\omega_{n}^0),f(\omega_{n}^1)...f(\omega_{n}^{n-1})\)就得到了这个多项式的点值表示
  • 具体做法就是利用一点单位根的性质,我们将奇偶项分开

\(A(x)=a_0+a_2x^2+a_4x^4+...\)
\(B(x)=a1+a_3x^3+a_5x^5+...\)
\(f(x)=A(x^2)+xB(x^2)\)
\(f(\omega_{n}^{k})=A(\omega_{n}^{2k})+\omega_{n}^kB(\omega_{n}^{2k})\)

\(f(\omega_{n}^{k})=A(\omega_{\frac{n}{2}}^{k})+\omega_{n}^kB(\omega_{\frac{n}{2}}^{k})\)
\(f(\omega_{n}^{k+n/2})=A(\omega_{\frac{n}{2}}^{k})-\omega_{n}^kB(\omega_{\frac{n}{2}}^{k})\)
那么我们直接递归下去就行

op=1

void fft(cp* a, int n, int op) {if (n == 1) return;cp a1[n / 2], a2[n / 2];for (int i = 0;i * 2 < n;++i) {a1[i] = a[2 * i];a2[i] = a[2 * i + 1];}fft(a1, n / 2, op);fft(a2, n / 2, op);cp wn = (cp){ cos(2 * pi / n), op*sin(2 * pi / n) }; cp w = (cp){ 1,0 };for (int i = 0;i < n / 2;++i) {a[i] = a1[i] + w * a2[i];a[i + n / 2] = a1[i] - w * a2[i];w = w * wn;}
}

乘法

假如我们将两个多项式都使用点值表示,并且是相同的n个点,那么我们直接对应相乘,就得到了乘积多项式的点值表示

点值->系数表示

  • 考虑使用拉格朗日插值将点值表示还原到系数表示

  • \(f(x)=\sum_{i=0}^{n-1}f(\omega_{n}^{i})L_i(x)\)

  • \(L_i(x)=\prod_{k\neq i}\frac{x-\omega_{n}^k}{\omega_{n}^i-\omega_{n}^k}\)

  • \(L_i(x)\)可以直接硬求,下面贴一个LLM的做法
    在这里插入图片描述
    在这里插入图片描述

  • 稍微简单一点的做法,利用单位根的正交性质

  • \(\sum_{k=0}^{n-1} \omega_{n}^{k(i-j)}=n\delta_{i,j}\)\(\delta_{i,j}\)为克罗内克符号,\(\delta_{i,j}\)为1当且仅当\(i=j\)

  • 那么我们要构造的\(L_i(x)\)本质上就是要让\(L_i(\omega_{n}^{j})=\delta_{i,j}\)

  • \(L_i(x)=\sum_{k=0}^{n-1} c_{i,k}x^k\)

  • \(\omega_{n}^{j}\)代入\(L_i(\omega_{n}^{j})=\sum_{k=0}^{n-1} c_{i,k}\omega_{n}^{j}\),那么我们对比一下它的正交性质的式子,只需令\(c_{i,k}=\frac{\omega_{n}^{-ik}}{n}\)就能搞定

  • 因此有\(f(x)=\frac{1}{n}\sum_{i=0}^{n-1} f(\omega_{n}^{i})\sum_{k=0}^{n-1}\omega_{n}^{-ki}x^k\)

  • \(f(x)=\frac{1}{n}\sum_{k=0}^{n-1}x^k \sum_{i=0}^{n-1}f(\omega_{n}^i)\omega_{n}^{-ki}\)

  • \(\sum_{i=0}^{n-1}f(\omega_{n}^i)\omega_{n}^{-ki}\)其实就是\(a_k\)

  • 那么\(a_0,a_1...a_{n-1}\) 我们可以看作是求\(g(x)=\sum_{i=0}^{n-1}f(\omega_{n}^i)x^i\)这个多项式在\(\omega_{n}^{-0},\omega_{n}^{-1}...\omega_{n}^{-(n-1)}\)的值

  • 而我们第一部分求的是\(f(x)=\sum_{i=0}^{n-1}a_ix^i\)\(\omega_{n}^{0},\omega_{n}^{1}...\omega_{n}^{(n-1)}\)的值,因此代码是可以复用的

蝶形优化

  • 蝶形优化其实就是自底向上计算,那么首先需要求得每个数最后在哪里?
  • 经过观察可以发现就是将它的二进制位进行一个翻转,比如n=8时(001->100,110->011)
  • 那么将每个数放到最后一层的正确位置后,自底向上计算即可
#include<bits/stdc++.h>
#define lc (o<<1)
#define rc ((o<<1)|1) 
using namespace std;
typedef long long ll;
typedef double db;
constexpr int N = 1 << 22;
constexpr ll inf = 1ll << 60;
const db pi = acos(-1);
struct cp {db x = 0, y = 0;cp(db x = 0, db y = 0) : x(x), y(y) {}
};
cp operator + (const cp& a, const cp& b) {return (cp) { a.x + b.x, a.y + b.y };
}
cp operator - (const cp& a, const cp& b) {return (cp) { a.x - b.x, a.y - b.y };
}
cp operator * (const cp& a, const cp& b) {return (cp) { a.x* b.x - a.y * b.y, a.x* b.y + a.y * b.x };
}
int n, m, r[N];
cp a[N], b[N], c[N];
void fft(cp* a, int n, int op) {for (int i = 0;i < n;++i) if (i < r[i]) swap(a[i], a[r[i]]);for (int i = 1;i < n;i *= 2) {cp wn = (cp){ cos(pi / i), sin(pi / i) * op };for (int j = 0;j < n;j += i << 1) {cp w = (cp){ 1,0 }, x, y;for (int k = 0;k < i;++k) {x = a[j + k];y = a[j + k + i];a[j + k] = x + w * y;a[j + k + i] = x - w * y;w = w * wn;}}}
}
void R(int& x) {int t = 0; char ch;for (ch = getchar();!('0' <= ch && ch <= '9');ch = getchar());for (;('0' <= ch && ch <= '9');ch = getchar()) t = t * 10 + ch - '0';x = t;
}
int main() {
#ifdef LOCALfreopen("data.in", "r", stdin);freopen("data.out", "w", stdout);
#endifcin >> n >> m;n++;m++;int t;for (int i = 0;i < n;++i) R(t), a[i].x = t;for (int i = 0;i < m;++i) R(t), b[i].x = t;int lim = 1;while (lim < n + m) lim <<= 1;for (int i = 0;i < lim;++i) {r[i] = r[i >> 1] >> 1;if (i & 1) r[i] += lim / 2;}fft(a, lim, 1);fft(b, lim, 1);for (int i = 0;i < lim;++i) c[i] = a[i] * b[i];fft(c, lim, -1);for (int i = 0;i <= n + m - 2;++i) printf("%d ", (int)(c[i].x / lim + 0.5));return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/939844.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2025.10.18——1黄

普及/提高- P14253 旅行(trip) CSP模拟赛T1,也是唯一AC的题。

幂等的双倍快乐,你值得拥有

hello, 这是有态度马甲的第xxx篇原创口水文。有趣指数5颗星,有用指数5颗星。 😠😠本文是国外技术网站medium上点赞超过200+的翻译/笔记文,有关规避/解决幂等请求的思路指南。 1. 软件领域二次请求无法避免 我们…

10.18总结

1.今天学习了数据模块化 2.明天用数据组完成数据整合

10.17总结

1.今天学习了如何转换数据格式 2.每天学习数据模块化

软考中级学习总结(2)

可靠性计算: (1)串联系统 R=R1R2R3......Rn (2)并联系统R=1-(1-R1)(1-R2).....(1-Rn) 编译程序和解释程序 1.低级语言:机器语言,汇编语言 2.高级语言:应用程序设计语言(java) 高级语言通过解释和编译后在机…

F - Not Adjacent

F - Not Adjacent Problem Statement You are given a length-$N$ integer sequence $A=(A _ 1,A _ 2,\ldots,A _ N)$. There are $2 ^ N$ (not necessarily contiguous) subsequences of $A$. Find how many subseque…

2025年粉末冶金制品/零件厂家推荐排行榜,高精度耐磨粉末冶金零件,优质粉末冶金制品公司推荐!

2025年粉末冶金制品/零件厂家推荐排行榜,高精度耐磨粉末冶金零件,优质粉末冶金制品公司推荐!一、行业背景介绍粉末冶金技术是一种先进的材料加工方法,通过将金属粉末或合金粉末经过压制和烧结等工艺,制备出具有特…

Neo4j 图数据库搭建和 Springboot 访问

Neo4j 图数据库主要用于节点关系的存储和查询,比传统关系型数据库的查询效率高,能够快速找到节点之间的最短路径,灵活强很强。 Neo4j 分为企业版和社区版,一般来说社区版免费,已经足够用了。有些功能只有企业版才…

AI元人文理论框架体系研究:价值原语化的文明演进机制与治理范式转变——声明Ai研究

AI元人文理论框架体系研究:价值原语化的文明演进机制与治理范式转变引言:AI元人文理论框架的兴起与核心问题1.1 理论背景与时代需求 在人工智能技术迅猛发展的2025年,人类社会正站在一个文明史的奇点上。通用人工智…

[buuctf]bjdctf_2020_router

首先查看一下文件的保护措施在用ida打开看一下 这里就是一个menu,然后进行选择,进入不同的函数这里主要注意到进入case1时,这里直接就有一个system函数,那么是否可以直接通过这个函数获得shell呢 在看看这里通过rea…

AtCoder Beginner Contest 428 ABCDE 题目解析

A - Grandmas Footsteps 题意 下课铃响起后,高桥会立即开始重复执行以下动作:以每秒 \(S\) 米的速度跑 \(A\) 秒,然后保持静止 \(B\) 秒。请问在下课铃响后 \(X\) 秒时,他总共跑了多少米? 思路 每 \(A+B\) 秒为一…

稻草火把下的星辰:回忆我的90年代求学路

1993年的夏天,我手握政和一中的录取通知书,却感觉这张纸比铅还重。中考成绩名列全校第一的喜悦,早已被无钱就读的现实冲刷得一干二净。在我们那个小村庄,考上高中并不被视为荣耀之事,唯有考上中专才被视为真正的“…

20251018

正睿 CSP 7 连测 终于 ak 了一场。 D 给定长度为 \(n(n \le 2 \times 10^5)\) 的序列 \(a(|a_i| \le 10^9)\)。若 \(a_i < 0\),\(b_i = -2^{-a_i}\);否则,\(b_i = 2^{a_i}\)。求 \(b\) 的最大子段和对 \(9982443…

Linux后门应急

Linux后门应急 1、主机后门用户名称:提交格式如:flag 进来先对终端升级一下 python -c import pty; pty.spawn("/bin/bash")直接使用cat /etc/passwd 查看后面用户flag{backdoor}2、主机排查项中可以发现到…

吴恩达深度学习课程一:神经网络和深度学习 第三周:浅层神经网络(二)

此分类用于记录吴恩达深度学习课程的学习笔记。 课程相关信息链接如下:原课程视频链接:[双语字幕]吴恩达深度学习deeplearning.ai github课程资料,含课件与笔记:吴恩达深度学习教学资料 课程配套练习(中英)与答案…

2025.10.18总结

今天继续学软考相关内容,看了操作系统一个章节进程管理的内容。 操作系统的定义:操作系统是指控制和管理整个计算机系统的硬件和软件资源,并合理地组织调度计算机的工作和资源的划分,以提供给用户和其他软件方便的…

C++动态多态原理分析

class Animal { public:void speak() {cout << "Animal.speak()" << endl;} };class Cat :public Animal {void speak() {cout << "Cat.speak()" << endl;} }; void doW…

Java基础——初识Math类,基本运算符,自增自减运算符,逻辑运算符,位运算符,三元运算符

Java基础——初识Math类,基本运算符,自增自减运算符,逻辑运算符,位运算符,三元运算符初识Math类 Math.pow(2,3); //运用工具类进行次方运算基本运算符 1.算术运算符:+,-,,/,%(此前为二元运算符),++,--(一…

ENC28J60

ENC28J60ENC28J60 是在嵌入式开发、物联网、单片机联网中常见的一种芯片。 我们来从硬件、软件、应用三个角度讲清楚它。🧩 一、基本定义ENC28J60 是 Microchip(微芯科技) 公司生产的一款 独立的以太网控制器芯片(…

第七章 常见攻击事件分析--钓鱼邮件

第七章 常见攻击事件分析--钓鱼邮件 1、请分析获取黑客发送钓鱼邮件时使用的IP,flag格式: flag 将文件下来到虚拟机解压有个钓鱼邮件.eml 查阅的时候觉得这里很奇怪,这里跟其他的不大一样,这里对来源进行了base64的…