题目大意:

给定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 ;
}

最新文章

  1. TinyFox v2.3.2 正式发布,跨平台的.NET OWIN WEB服务器
  2. CF467 AB 水题
  3. 利用Spring创建定时任务
  4. openfire教程网
  5. iOS开发——UI篇Swift篇&amp;玩转UItableView(三)分组功能
  6. 数据交互 ajax代码整理
  7. sqlite数据库修改及升级
  8. O-C相关-03:面向对象概念的具体介绍
  9. iOS内存管理系列之二:自动释放与便捷方法
  10. 构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(18)-权限管理系统-表数据
  11. 网页动态切换母版页(MasterPage)
  12. android 使用Vysor投影到电脑
  13. AutoCAD 2019 for Mac 特别版(附注册机)
  14. mysql导入本地文件(作业)
  15. vue.js 添加 fastclick的支持
  16. 【LeetCode OJ】Majority Element
  17. ASP.NET MVC View使用Conditional compilation symbols
  18. 使用ksync 加速基于k8s 的应用开发
  19. AngularX Http服务总结
  20. System.Security.Cryptography.CryptographicException: 系统找不到指定的文件

热门文章

  1. 关于元素的offsetHeight、line-htight
  2. Java——super关键字
  3. js条件语句,用if...else if....else方程ax2+bx+c=0一元二次方程。求根
  4. 思维题+贪心——牛客多校第一场C
  5. [JZOJ 5810] 简单的玄学
  6. Codeforces786B
  7. TCP/IP点滴
  8. 17-MySQL-Ubuntu-数据表的查询-分页(六)
  9. Spring MVC @PathVariable注解(3)
  10. Nginx+win10安装配置