HDU - 1402,A * B Problem Plus,FFT板

HDU - 1402,A * B Problem Plus

https://vjudge.net/problem/HDU-1402/origin
Calculate A * B.
思路:FFT板题,贴个常数很小的板子

#include<bits/stdc++.h>
#define ll long long
#define ri register int
#define MAXN 50005
using namespace std;
const double pi=acos(-1.0);
struct cpx
{
    double r, i;
    inline void operator +=(const cpx &b){ r+=b.r, i+=b.i;}
    inline cpx operator +(const cpx &b)const{ return (cpx){r+b.r, i+b.i};}
    inline cpx operator -(const cpx &b)const{ return (cpx){r-b.r, i-b.i};}
    inline cpx operator *(const cpx &b)const{ return (cpx){r*b.r-i*b.i, r*b.i+i*b.r};}
    inline cpx operator *(const double b)const{ return (cpx){r*b, i*b};}
    inline cpx operator ~()const{return (cpx){r, -i};}
}a[MAXN<<2], b[MAXN<<2], w[MAXN<<2];

inline void DFT_(cpx *f, int n)
{
    for(ri i=0, j=0; i<n; ++i)
    {
        if(i>j) swap(f[i], f[j]);
        for(ri k=n>>1; (j^=k)<k; k>>=1);
    }
    for(ri i=1; i<n; i<<=1) for(ri j=0; j<n; j+=i<<1)
            for(ri k=j; k<j+i; ++k)
            {
                cpx t=w[i+k-j]*f[k+i];
                f[k+i]=f[k]-t, f[k]+=t;
            }
}
inline void DFT(cpx *f, int n)
{
    if(n==1) return;
    n>>=1;
    static cpx a[MAXN<<1];
    for(ri i=0; i<n; ++i) a[i]=(cpx){f[i<<1].r, f[i<<1|1].r};
    DFT_(a, n);
    for(ri i=0; i<n; ++i)
    {
        cpx q=~a[(n-i)&(n-1)], x=(a[i]+q)*0.5, y=(a[i]-q)*(cpx){0, -0.5}, t=y*w[n+i];
        f[i]=x+t, f[n+i]=x-t;
    }
}
inline void IDFT(cpx *f, int n)
{
    if(n==1) return;
    reverse(f+1, f+n), n>>=1;
    static cpx a[MAXN<<1];
    for(ri i=0; i<n; ++i)
        a[i]=(f[i]+f[i+n])*0.5 + (f[i]-f[i+n])*(cpx){0, 0.5}*w[n+i];
    DFT_(a, n);
    double k=1.0/n;
    for(ri i=0; i<n; ++i) f[i<<1]=(cpx){a[i].r*k, 0}, f[i<<1|1]=(cpx){a[i].i*k, 0};
}
void transfer(int a[], int n)//因为是求大整数,需进位
{
    int t = 0;
    for(int i = 0; i < n; i++)
    {
        a[i] += t;
        if(a[i] > 9)
        {
            t = a[i] / 10;
            a[i] %= 10;
        }
        else t = 0;
    }
}
char s1[MAXN],s2[MAXN];
int len1,len2,len,sum[MAXN<<2];
inline void conv(cpx a[], cpx b[], int n)//将多项式相乘并把系数放入sum
{
    DFT(a, len), DFT(b, len);
    for(ri i=0; i<n; ++i)
        a[i]=a[i]*b[i];
    IDFT(a, len);
    for(int i = 0;i < len;i++)//提取出系数
        sum[i] = (int)(a[i].r+0.5);
}
inline void init()//将多项式的项数扩充至2^n
{
    len1 = strlen(s1);
    len2 = strlen(s2);
    len = 1;
    while(len < len1+len2)len<<=1;
    for(int i = 0;i < len1;i++)
        a[i] = (cpx){(double)(s1[len1-1-i]-'0'),0};
    for(int i = len1;i < len;i++)
        a[i] = (cpx){0,0};
    for(int i = 0;i < len2;i++)
        b[i] = (cpx){(double)(s2[len2-1-i]-'0'),0};
    for(int i = len2;i < len;i++)
        b[i] = (cpx){0,0};
    for(ri i=1; i<len; i<<=1)
    {
        w[i]=(cpx){1, 0};
        for(ri j=1; j<i; ++j)
            w[i+j]=((j&31)==1?(cpx){cos(pi*j/i), sin(pi*j/i)}:w[i+j-1]*w[i+1]);
    }
}
int main()
{
    while(~scanf("%s%s",s1,s2))//输入两个多项式的长度及模数,注意这里的长度比实际长度小1
    {
        init();
        conv(a,b,len);
        transfer(sum,len);

        len = len1+len2-1;
        while(sum[len] <= 0 && len > 0)len--;//舍去前导0
        for(int i = len;i >= 0;i--)
            printf("%c",sum[i]+'0');
        printf("\n");
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值