BZOJ 2179 FFT快速傅立叶

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


【题目分析】
FFT裸题用来快速计算高精度的乘法,从n^2变成了n。其实不会,随便抄了一个模板。以后再慢慢学。


【代码】

#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) n--;//确定第一个数的位置 
    for (int i=n;i>=0;--i) putchar(ans[i]+'0');//输出 
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值