首页 > 其他 > 详细

【模板】快速傅里叶变换(FFT)(BZOJ2179)

时间:2019-01-12 20:44:01      阅读:155      评论:0      收藏:0      [点我收藏+]

Description

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

Input

第一行一个正整数n。 第二行描述一个位数为n的正整数x。 第三行描述一个位数为n的正整数y。

Output

输出一行,即x*y的结果。

Code

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<complex>
#define cp complex <double>
using namespace std;
const double pi=acos(-1);
int l,n,res[1000010];
cp a[1000010],b[1000010],arr[1000010],inv[1000010];
char str1[1000010],str2[1000010];
void init()
{
    for (int i=0;i<n;i++)
    {
        arr[i]=cp(cos(2*pi*i/n),sin(2*pi*i/n));
        inv[i]=conj(arr[i]);
    }
}
void FFT(cp *a,cp *arr)
{
    int lim=0;
    while ((1<<lim)<n) lim++;
    for (int i=0;i<n;i++)
    {
        int t=0;
        for (int j=0;j<lim;j++)
            if ((i>>j) & 1) t|=1<<(lim-j-1);
        if (i<t) swap(a[i],a[t]);
    }
    for (int l=2;l<=n;l*=2)
    {
        int m=l/2;
        for (cp *buf=a;buf!=a+n;buf+=l)
            for (int i=0;i<m;i++)
            {
                cp t=arr[n/l*i]*buf[i+m];
                buf[i+m]=buf[i]-t;
                buf[i]+=t;
            }
    }
}
int main()
{
    scanf("%d",&l);
    scanf("%s",str1);scanf("%s",str2);
    n=1;while (n<2*l) n<<=1;
    init();
    for (int i=0;i<l;i++) a[l-i-1].real(str1[i]-'0');
    for (int i=0;i<l;i++) b[l-i-1].real(str2[i]-'0');
    FFT(a,arr),FFT(b,arr);
    for (int i=0;i<n;i++) a[i]*=b[i];
    FFT(a,inv);
    for (int i=0;i<n;i++)
    {
        res[i]+=floor(a[i].real()/n+0.5);
        res[i+1]+=res[i]/10;
        res[i]%=10;
    }
    for (int i=res[2*l-1]?2*l-1:2*l-2;i>=0;i--)
        putchar('0'+res[i]);
    puts("");
    return 0;
}

【模板】快速傅里叶变换(FFT)(BZOJ2179)

原文:https://www.cnblogs.com/Code-Geass/p/10260917.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!