题目大意:

给定l,输入两个位数为l的数A B

输出两者的乘积

FFT讲解 这个讲解蛮好的 就是讲解里面贴的模板是错误的

struct cpx {
double x,y;
cpx(double _x=0.0,double _y=0.0) {
x=_x; y=_y;
}
cpx operator -(const cpx &b) const {
return cpx(x-b.x,y-b.y);
}
cpx operator +(const cpx &b) const {
return cpx(x+b.x,y+b.y);
}
cpx operator *(const cpx &b) const {
return cpx(x*b.x-y*b.y,x*b.y+y*b.x);
}
}; void change(cpx a[],int len) /// 位置互换 len必须是2的幂
{
for(int i=,j=len/;i<len-;i++) {
if(i<j) swap(a[i],a[j]);
int k=len/;
while(j>=k) j-=k, k>>=;
if(j<k) j+=k;
}
} #define PI acos(-1)
void fft(cpx a[],int len,int on)/// len必须是2的幂 on为1时dft -1时idft
{
change(a,len);
for(int i=;i<len;i <<= ) {
cpx wn(cos(PI/i),on*sin(PI/i));
for(int j=;j<len;j+=(i<<)) {
cpx w(,);
for(int k=;k<i;k++,w=w*wn) {
cpx u=a[j+k], v=w*a[j+k+i];
a[j+k]=u+v, a[j+k+i]=u-v;
}
}
}
if(on==-) {
for(int i=;i<len;i++)
a[i].x/=len;
}
}

FFT模板1

题解讲解

struct cpx {
double x,y;
cpx(double _x=0.0,double _y=0.0) {
x=_x; y=_y;
}
cpx operator - (const cpx &b)const {
return cpx(x-b.x,y-b.y);
}
cpx operator + (const cpx &b)const {
return cpx(x+b.x,y+b.y);
}
cpx operator * (const cpx &b)const {
return cpx(x*b.x-y*b.y,x*b.y+y*b.x);
}
};
void fft(cpx a[],int on)
{
for(int i=;i<len;i++)
if(i<r[i]) swap(a[i],a[r[i]]);
for(int i=;i<len;i<<=) {
cpx wn(cos(PI/i),on*sin(PI/i));
for(int j=;j<len;j+=(i<<)) {
cpx w(,);
for(int k=;k<i;k++,w=w*wn) {
cpx u=a[j+k], v=w*a[j+k+i];
a[j+k]=u+v, a[j+k+i]=u-v;
}
}
}
}
int main()
{
......
while(len<d*) len <<= , l++; // 将长度补到2的幂
for(int i=;i<len;i++)
r[i]=( r[i>>]>> )|( (i&)<<(l-) );
......
}

FFT模板2

这题是把两个数看成

A=a1*10^0+a2*10^1+a3*10^2...+al*10^(l-1)

B=b1*10^0+b2*10^1+b3*10^2...+bl*10^(l-1)

的形式

这样就变成了多项式相乘

#include <bits/stdc++.h>
#define PI acos(-1)
#define MAXN 300004
using namespace std; struct cpx{
double x,y;
cpx(double _x=0.0,double _y=0.0) {
x=_x; y=_y;
}
cpx operator-(const cpx &b)const {
return cpx(x-b.x,y-b.y);
}
cpx operator+(const cpx &b)const {
return cpx(x+b.x,y+b.y);
}
cpx operator*(const cpx &b)const {
return cpx(x*b.x-y*b.y,x*b.y+y*b.x);
}
}x1[MAXN/], x2[MAXN/]; char str1[MAXN/], str2[MAXN/];
int sum[MAXN], l; void change(cpx a[],int len) /// 位置互换 len必须是2的幂
{
for(int i=,j=len/;i<len-;i++) {
if(i<j) swap(a[i],a[j]);
int k=len/;
while(j>=k) {
j-=k, k >>= ;
}
if(j<k) j+=k;
}
} void fft(cpx a[],int len,int on)/// len必须是2的幂 on为1时dft -1时idft
{
change(a,len);
for(int i=;i<len;i <<= ) {
cpx wn(cos(PI/i),on*sin(PI/i));
for(int j=;j<len;j+=(i<<)) {
cpx w(,);
for(int k=;k<i;k++,w=w*wn) {
cpx u=a[j+k], t=w*a[j+k+i];
a[j+k]=u+t, a[j+k+i]=u-t;
}
}
}
if(on==-) {
for(int i=;i<len;i++)
a[i].x/=len;
}
} int main()
{
while(~scanf("%d",&l)) {
scanf("%s%s",str1,str2);
int len=;
while(len<l*) len <<= ; // 将长度补到2的幂
for(int i=;i<l;i++)
x1[i]=cpx(str1[l--i]-'',),
x2[i]=cpx(str2[l--i]-'',);
for(int i=l;i<len;i++)
x1[i]=x2[i]=cpx(,); // 不足补0 fft(x1,len,); fft(x2,len,); /// dft转为点值表达
for(int i=;i<len;i++) x1[i]=x1[i]*x2[i]; // 计算
fft(x1,len,-); /// idft转为系数表达 for(int i=;i<len;i++)
sum[i]=(int)(x1[i].x+0.1); // 四舍五入
for(int i=;i<len;i++)
sum[i+]+=sum[i]/, sum[i]%=; // 进制
while(sum[len]== && len>) len--; // 去前导0
for(int i=len;i>=;i--)
printf("%d",sum[i]); printf("\n");
} return ;
}

两种模板的细节区别在于

(2)在四舍五入时除len ,而(1)是在FFT中判断开关on再除len

#include <bits/stdc++.h>
#define PI acos(-1.0)
const int MAXN=;
using namespace std; struct cpx {
double x,y;
cpx(double _x=0.0,double _y=0.0) {
x=_x; y=_y;
}
cpx operator - (const cpx &b)const {
return cpx(x-b.x,y-b.y);
}
cpx operator + (const cpx &b)const {
return cpx(x+b.x,y+b.y);
}
cpx operator * (const cpx &b)const {
return cpx(x*b.x-y*b.y,x*b.y+y*b.x);
}
}x1[MAXN], x2[MAXN]; int n, m, len=;
int l, r[MAXN], sum[MAXN];
char str1[MAXN],str2[MAXN]; void fft(cpx a[],int on)
{
for(int i=;i<len;i++)
if(i<r[i]) swap(a[i],a[r[i]]);
for(int i=;i<len;i<<=) {
cpx wn(cos(PI/i),on*sin(PI/i));
for(int j=;j<len;j+=(i<<)) {
cpx w(,);
for(int k=;k<i;k++,w=w*wn) {
cpx u=a[j+k], v=w*a[j+k+i];
a[j+k]=u+v, a[j+k+i]=u-v;
}
}
}
} int main()
{
int d;
while(~scanf("%d",&d)) {
scanf("%s%s",str1,str2);
while(len<d*) len <<= , l++; // 将长度补到2的幂
for(int i=;i<d;i++)
x1[i]=cpx(str1[d--i]-'',),
x2[i]=cpx(str2[d--i]-'',);
for(int i=;i<len;i++)
r[i]=( r[i>>]>> )|( (i&)<<(l-) ); fft(x1,); fft(x2,); /// dft转为点值表达
for(int i=;i<len;i++) x1[i]=x1[i]*x2[i]; // 计算
fft(x1,-); /// idft转为系数表达 for(int i=;i<len;i++)
sum[i]=(int)(x1[i].x/len+0.1); // 四舍五入
for(int i=;i<len;i++)
sum[i+]+=sum[i]/, sum[i]%=; // 进制
while(sum[len]== && len>) len--; // 去前导0
for(int i=len;i>=;i--)
printf("%d",sum[i]); printf("\n");
} return ;
}

P1919 【模板】A*B Problem升级版 /// FFT模板的更多相关文章

  1. 洛谷.1919.[模板]A*B Problem升级版(FFT)

    题目链接:洛谷.BZOJ2179 //将乘数拆成 a0*10^n + a1*10^(n-1) + ... + a_n-1的形式 //可以发现多项式乘法就模拟了竖式乘法 所以用FFT即可 注意处理进位 ...

  2. HDU 1402 A * B Problem Plus (FFT模板题)

    FFT模板题,求A*B. 用次FFT模板需要注意的是,N应为2的幂次,不然二进制平摊反转置换会出现死循环. 取出结果值时注意精度,要加上eps才能A. #include <cstdio> ...

  3. [hdu1402]A * B Problem Plus(FFT模板题)

    解题关键:快速傅里叶变换fft练习. 关于结果多项式长度的确定,首先将短多项式扩展为长多项式,然后扩展为两倍. #include<cstdio> #include<cstring&g ...

  4. 【洛谷P1919】A*B Problem升级版

    题目大意:rt 题解:将长度为 N 的大整数看作是一个 N-1 次的多项式,利用 FFT 计算多项式的卷积即可. 代码如下 #include <bits/stdc++.h> using n ...

  5. 洛谷P1919 【模板】A*B Problem升级版 题解(FFT的第一次实战)

    洛谷P1919 [模板]A*B Problem升级版(FFT快速傅里叶) 刚学了FFT,我们来刷一道模板题. 题目描述 给定两个长度为 n 的两个十进制数,求它们的乘积. n<=100000 如 ...

  6. 再写FFT模板

    没什么好说的,今天又考了FFT(虽然不用FFT也能过)但是确实有忘了怎么写FFT了,于是乎只有重新写一遍FFT模板练一下手了.第一部分普通FFT,第二部分数论FFT,记一下模数2^23*7*17+1 ...

  7. FFT模板(多项式乘法)

    FFT模板(多项式乘法) 标签: FFT 扯淡 一晚上都用来捣鼓这个东西了...... 这里贴一位神犇的博客,我认为讲的比较清楚了.(刚好适合我这种复数都没学的) http://blog.csdn.n ...

  8. FFT/NTT总结+洛谷P3803 【模板】多项式乘法(FFT)(FFT/NTT)

    前言 众所周知,这两个东西都是用来算多项式乘法的. 对于这种常人思维难以理解的东西,就少些理解,多背板子吧! 因此只总结一下思路和代码,什么概念和推式子就靠巨佬们吧 推荐自为风月马前卒巨佬的概念和定理 ...

  9. 2018.08.28 洛谷P3803 【模板】多项式乘法(FFT)

    传送门 fft模板题. 终于学会fft了. 这个方法真是神奇! 经过试验发现手写的complex快得多啊! 代码: #include<iostream> #include<cstdi ...

随机推荐

  1. R语言 基本语法

    R语言基本语法 我们将开始学习R语言编程,首先编写一个"你好,世界! 的程序. 根据需要,您可以在R语言命令提示符处编程,也可以使用R语言脚本文件编写程序. 让我们逐个体验不同之处. 命令提 ...

  2. 【网络】IP地址,子网掩码,网段表示法,默认网关,DNS服务器详解

    楔子: 以Windows系统中IP地址设置界面为参考(如图1), IP地址, 子网掩码, 默认网关 和 DNS服务器, 这些都是什么意思呢? 学习IP地址的相关知识时还会遇到网络地址,广播地址,子网等 ...

  3. 树形dp换根,求切断任意边形成的两个子树的直径——hdu6686

    换根dp就是先任取一点为根,预处理出一些信息,然后在第二次dfs过程中进行状态的转移处理 本题难点在于任意割断一条边,求出剩下两棵子树的直径: 设割断的边为(u,v),设down[v]为以v为根的子树 ...

  4. 牛客多校第三次B——线段树维护线性基交

    写线性基交函数时调试了半天.. #include<bits/stdc++.h> using namespace std; #define ll long long #define maxn ...

  5. NX二次开发-UFUN初始化UF_initialize

    在调用UFUN函数时必须加Uf.h头文件,代码开头和结尾加UF_initialize和UF_terminate NX9+VS2012 #include <uf.h> #include &l ...

  6. NX二次开发-UFUN建模创建特征组UF_MODL_create_set_of_feature

    NX11+VS2013 #include <uf.h> #include <uf_modl.h> UF_initialize(); //创建块 UF_FEATURE_SIGN ...

  7. Linux命令(2):cat

    cat命令是一个文本连接和查看的命令,用于文件的输出显示. 三大功能 一次显示整个文件. $ cat filename 从键盘创建一个文件.只能创建新文件,不能编辑已有文件. $ cat > f ...

  8. easyUI tabs 显示与隐藏 tab 页

    隐藏: tab_option = $('#tabs').tabs('getTab'," 单位信息 ").panel('options').tab; tab_option.hide( ...

  9. opencv-图像形态学之膨胀腐蚀

    转自:https://blog.csdn.net/poem_qianmo/article/details/23710721 一.原理 1.1 形态学概述 形态学(morphology)一词通常表示生物 ...

  10. console.log("正常-普天数据已调用");

    console.log("正常-普天数据已调用");