您的位置:首页 > 其它

BZOJ 2179 FFT快速傅立叶 题解

2016-07-03 11:06 309 查看
bzoj 2179


Description
给出两个n位10进制整数x和y,你需要计算x*y。



【题目分析】

高精裸题。练手。

【代码】

1、手动高精

#include<bits/stdc++.h>
using namespace std;
const double pi=acos(-1.0);
int rev[200001],ans[200001],len,n,m;
char s[200001];
struct P
{
double x,y;
inline P operator +(P a) {return (P){x+a.x,y+a.y};}
inline P operator -(P a) {return (P){x-a.x,y-a.y};}
inline P operator *(P a) {return (P){x*a.x-y*a.y,x*a.y+y*a.x};}
}a[200001],b[200001],c[200001];
inline void fft(P *x,int n,int flag)//快速傅立叶变换
{
for (int i=0;i<n;++i) if (rev[i]>i) swap(x[rev[i]],x[i]);
for(int m=2;m<=n;m<<=1)
{
P wn=(P){cos(2.0*pi/m*flag),sin(2.0*pi/m*flag)};
for(int i=0;i<n;i+=m)
{
P w=(P){1.0,0};int mid=m>>1;
for (int j=0;j<mid;++j)
{
P u=x[i+j],v=x[i+j+mid]*w;
x[i+j]=u+v;x[i+j+mid]=u-v;
w=w*wn;
}
}
}
}
int main()
{
scanf("%d",&n);
scanf("%s",s);for (int i=0;i<n;++i) a[i].x=s[n-i-1]-'0';
scanf("%s",s);for (int i=0;i<n;++i) b[i].x=s[n-i-1]-'0';
m=1;n=n*2-1;
while (m<=n) m<<=1,len++; n=m;
for (int i=0;i<n;++i)
{
int t=i,ret=0;
for (int j=1;j<=len;++j) ret<<=1,ret|=t&1,t>>=1;
rev[i]=ret;
}
fft(a,n,1);fft(b,n,1);//转过去
for (int i=0;i<n;++i) c[i]=a[i]*b[i];//高效率高精度
fft(c,n,-1);//又回来
for (int i=0;i<n;++i) ans[i]=(c[i].x/n)+0.5;//精度误差
for (int i=0;i<n;++i) ans[i+1]+=ans[i]/10,ans[i]%=10;//进位
n++;
while (!ans
&&n) n--;//确定第一个数的位置
for (int i=n;i>=0;--i) putchar(ans[i]+'0');//输出
}


FFT
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: