题目大意:

给定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. 将map转为Object,支持 Date/Boolean

    import lombok.extern.log4j.Log4j2; import java.lang.reflect.Field; import java.lang.reflect.Method; ...

  2. 全球首个开放应用模型 OAM 开源

    业界要闻 全球首个开放应用模型 OAM 开源 2019 年 10 月 17 日,阿里巴巴合伙人.阿里云智能基础产品事业部总经理蒋江伟(花名:小邪)在 Qcon 上海重磅宣布,阿里云与微软联合推出开放应 ...

  3. tesserocr与pytesseract模块的使用

    1.tesserocr的使用 #从文件识别图像字符 In [7]: tesserocr.file_to_text('image.png') Out[7]: 'Python3WebSpider\n\n' ...

  4. luoguP4768 [NOI2018]归程

    传送门 kruskal重构树: kruskal合并两个联通块时合并的边一定是联通块中权值最大的边,小于等于这条边的边所能联通的所有点在这个联通块中. 在合并两个联通块的时候新建一个点作为两个联通块代表 ...

  5. csp-s模拟测试91

    csp-s模拟测试91 倒悬吃屎的一套题. $T1$认真(?)分析题意发现复杂度不能带$n$(?),计划直接维护答案,考虑操作对答案的影响,未果.突然发现可以动态开点权值线段树打部分分,后来$Tm$一 ...

  6. 9、从命令行运行postman脚本及生成测试报告

    本节建议直接看postman官网:https://www.npmjs.com/package/newman 环境准备: 安装nodejs和npm     参考 https://www.runoob.c ...

  7. 2019 IEEEXtreme 13.0 题解记录

    比赛时间 2019.10.19 8:00 - 2019.10.20 8:00 比赛网站 https://csacademy.com/ieeextreme13 // 连续24小时做题真的是极限体验 // ...

  8. 干货:Java技术栈18年02月精彩好文汇总

    一晃眼,一个月过去了,新年也过完了. 一晃眼,又老了一岁了,感觉新的一年压力更大了. 我们也该为这一个月的技术做做汇总了,错过的同学正好可以统一回顾看看,已经看过的同学也可以再温习一下.. Java技 ...

  9. 线性可分SVM中线性规划问题的化简

    在网上找了许多关于线性可分SVM化简的过程,但似乎都不是很详细,所以凭借自己的理解去详解了一下. 线性可分SVM的目标是求得一个超平面(其实就是求w和b),在其在对目标样本的划分正确的基础上,使得到该 ...

  10. 控制音量大小widget

    由于手机音量按键非常悲剧的掉了.无法控制手机音量大小.使用起来非常不方便.所以决定写一个小widget放在桌面能够随时控制音量吧.也算是解决一点便利问题. 1.一个简单的widget 由于我的需求非常 ...