BZOJ 2194 快速傅立叶变换之二 | FFT
BZOJ 2194 快速傅立叶变换之二
题意
给出两个长为\(n\)的数组\(a\)和\(b\),\(c_k = \sum_{i = k}^{n - 1} a[i] * b[i - k]\)。
题解
我们要把这个式子转换成多项式乘法的形式。
一个标准的多项式乘法是这样的:
\]
来看看原式:
\]
将a翻转得到a':
\]
调整求和指标:
\]
那么求出\(c_k\),之后取\(c\)的前\(n\)位,倒着输出即可。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <complex>
#define space putchar(' ')
#define enter putchar('\n')
using namespace std;
typedef long long ll;
template <class T>
void read(T &x){
char c;
bool op = 0;
while(c = getchar(), c < '0' || c > '9')
if(c == '-') op = 1;
x = c - '0';
while(c = getchar(), c >= '0' && c <= '9')
x = x * 10 + c - '0';
if(op) x = -x;
}
template <class T>
void write(T x){
if(x < 0) putchar('-'), x = -x;
if(x >= 10) write(x / 10);
putchar('0' + x % 10);
}
const int N = 1000005;
const double PI = acos(-1);
typedef complex<double> cp;
int len, ta[N], tb[N], res[N];
cp omg[N], inv[N];
void init(int n){
for(int i = 0; i < n; i++){
omg[i] = cp(cos(2 * PI * i / n), sin(2 * PI * i / n));
inv[i] = conj(omg[i]);
}
}
void fft(cp *a, int n, cp *omg){
int lim = 0;
while((1 << lim) < n) lim++;
for(int i = 0; i < n; i++){
int t = 0;
for(int j = 0; j < lim; j++)
if(i >> j & 1) t |= 1 << (lim - j - 1);
if(i < t) swap(a[i], a[t]);
}
for(int l = 2; l <= n; l *= 2){
int m = l / 2;
for(cp *p = a; p != a + n; p += l)
for(int i = 0; i < m; i++){
cp t = omg[n / l * i] * p[m + i];
p[m + i] = p[i] - t;
p[i] += t;
}
}
}
void multiply(){
static cp a[N], b[N];
for(int i = 0; i < len; i++)
a[i].real(ta[i]), b[i].real(tb[i]);
int n = 1;
while(n < 2 * len) n *= 2;
init(n);
fft(a, n, omg);
fft(b, n, omg);
for(int i = 0; i < n; i++)a[i] *= b[i];
fft(a, n, inv);
for(int i = 0; i < n; i++)
res[i] = floor(a[i].real() / n + 0.5);
}
int main(){
read(len);
for(int i = 0; i < len; i++)
read(ta[i]), read(tb[i]);
for(int i = 0, j = len - 1; i < j; i++, j--)
swap(ta[i], ta[j]);
multiply();
for(int i = len - 1; i >= 0; i--)
write(res[i]), enter;
return 0;
}
BZOJ 2194 快速傅立叶变换之二 | FFT的更多相关文章
- bzoj 2194: 快速傅立叶之二 -- FFT
2194: 快速傅立叶之二 Time Limit: 10 Sec Memory Limit: 259 MB Description 请计算C[k]=sigma(a[i]*b[i-k]) 其中 k & ...
- bzoj 2194 快速傅立叶之二 —— FFT
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2194 如果把 a 序列翻转,则卷积得到的是 c[n-i],再把得到的 c 序列翻转即可. 代 ...
- BZOJ 2194 快速傅立叶之二 ——FFT
[题目分析] 咦,这不是卷积裸题. 敲敲敲,结果样例也没过. 看看看,卧槽i和k怎么反了. 艹艹艹,把B数组取个反. 靠靠靠,怎么全是零. 算算算,最终的取值范围算错了. 交交交,总算是A掉了. [代 ...
- BZOJ.2194.快速傅立叶之二(FFT 卷积)
题目链接 \(Descripiton\) 给定\(A[\ ],B[\ ]\),求\[C[k]=\sum_{i=k}^{n-1}A[i]*B[i-k]\ (0\leq k<n)\] \(Solut ...
- [BZOJ]2194: 快速傅立叶之二
题目大意:给定序列a,b,求序列c满足c[k]=sigma(a[i]*b[i-k]) (k<=i<n).(n<=10^5) 思路:观察发现就是普通的卷积反一反(翻转ab其中一个后做卷 ...
- 【刷题】BZOJ 2194 快速傅立叶之二
Description 请计算C[k]=sigma(a[i]*b[i-k]) 其中 k < = i < n ,并且有 n < = 10 ^ 5. a,b中的元素均为小于等于100的非 ...
- bzoj 2194: 快速傅立叶之二【NTT】
看别的blog好像我用了比较麻烦的方法-- (以下的n都--过 \[ c[i]=\sum_{j=i}^{n}a[i]*b[j-i] \] 设j=i+j \[ c[i]=\sum_{j=0}^{n-i} ...
- 【BZOJ 2194】2194: 快速傅立叶之二(FFT)
2194: 快速傅立叶之二 Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 1273 Solved: 745 Description 请计算C[k]= ...
- 快速傅立叶变换(FFT)算法
已知多项式f(x)=a0+a1x+a2x2+...+am-1xm-1, g(x)=b0+b1x+b2x2+...+bn-1xn-1.利用卷积的蛮力算法,得到h(x)=f(x)g(x),这一过程的时间复 ...
随机推荐
- Netty源码分析第3章(客户端接入流程)---->第3节: NioSocketChannel的创建
Netty源码分析第三章: 客户端接入流程 第三节: NioSocketChannel的创建 回到上一小节的read()方法: public void read() { //必须是NioEventLo ...
- Spring AOP部分源码分析
Spring源码流程分析-AOP相关 根据Spring源码整理,其中Calculator为自定义的实现方法. AnnotationConfigApplicationContext()加载配置类的流程 ...
- salt-api https连接问题
在非salt-api的主机上测试api连通性,测试代码如下: #!/usr/bin/env python import pycurl import StringIO import ssl ssl._c ...
- tree命令详解
基础命令学习目录首页 原文链接:http://man.linuxde.net/tree -a:显示所有文件和目录:-A:使用ASNI绘图字符显示树状图而非以ASCII字符组合:-C:在文件和目录清单加 ...
- 关于linux下的命令
1.文件和目录操作命令 pwd:显示当前的工作目录 cd:切换目录 tree:以树形结构图显示目录下的所有内容 mkdir:创建目录 touch:创建空文件或改变文件的时间戳属性 ls:显示目录下的内 ...
- redis使用哈希槽实现集群
Redis Cluster集群 一.redis-cluster设计 Redis集群搭建的方式有多种,例如使用zookeeper等,但从redis 3.0之后版本支持redis-cluster集群,Re ...
- 随手记录-linux-添加epel源
下载各种yum源 https://opsx.alibaba.com/mirror https://blog.csdn.net/harbor1981/article/details/51135623
- Java第一次试验
北京电子科技学院(BESTI) 实 验 报 告 课程:Java程序设计 班级:1352 姓名:朱国庆 学号:20135237 成绩: ...
- 第三周vim入门学习2
一.vim重复命令 1.重复执行上次命令 在普通模式下.(小数点)表示重复上一次的命令操作 拷贝测试文件到本地目录 $ cp /etc/protocols . 打开文件进行编辑 $ vim proto ...
- 软件项目的开发之svn的使用
Svn简介 SVN全名Subversion,即版本控制系统.SVN与CVS一样,是一个跨平台的软件,支持大多数常见的操作系统.作为一个开源的版本控制系统,Subversion管理着随时间改变的数据.这 ...