[FFT] HDU 1402

借着别人的码装完逼就跑系列

一个写的堪称完美的贴纸:
http://www.gatevin.moe/acm/fft%E7%AE%97%E6%B3%95%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/

FFT模板 计算A * B

#include <algorithm>
#include <bitset>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <vector>


using namespace std;
const double eps ( 1e-8 );
typedef long long lint;

const double PI = acos ( -1.0 );

struct Complex {
        double real, image;
        Complex ( double _real, double _image ) {
                real = _real;
                image = _image;
        }
        Complex () {}
};

Complex operator+ ( const Complex &c1, const Complex &c2 ) {
        return Complex ( c1.real + c2.real, c1.image + c2.image );
}

Complex operator- ( const Complex &c1, const Complex &c2 ) {
        return Complex ( c1.real - c2.real, c1.image - c2.image );
}

Complex operator* ( const Complex &c1, const Complex &c2 ) {
        return Complex ( c1.real * c2.real - c1.image * c2.image,
                         c1.real * c2.image + c1.image * c2.real );
}

// 循环FFT的顺序刚好是每个id位逆序排序后的顺序
int rev ( int id, int len ) {
        int ret = 0;
        for ( int i = 0; ( 1 << i ) < len; i++ ) {
                ret <<= 1;
                if ( id & ( 1 << i ) )
                        ret |= 1;
        }
        return ret;
}

//当DFT= 1时是DFT, DFT = -1则是逆DFT
Complex A[ 140000 ];
void IterativeFFT ( Complex *a, int len, int DFT ) //对长度为len(2的幂)的数组进行DFT变换
{
        // Complex *A = new Complex[ len ]; //用A数组存储数组a分组之后新的顺序
        for ( int i = 0; i < len; i++ )
                A[ rev ( i, len ) ] = a[ i ];
        for ( int s = 1; ( 1 << s ) <= len; s++ ) {
                int m = ( 1 << s );
                Complex wm = Complex ( cos ( DFT * 2 * PI / m ), sin ( DFT * 2 * PI / m ) );
                for ( int k = 0; k < len; k += m ) //这一层结点的包含数组元素个数都是(1 << s)
                {
                        Complex w = Complex ( 1, 0 );
                        for ( int j = 0; j < ( m >> 1 );
                              j++ ) //折半引理, 根据两个子节点计算父亲节点
                        {
                                Complex t = w * A[ k + j + ( m >> 1 ) ];
                                Complex u = A[ k + j ];
                                A[ k + j ] = u + t;
                                A[ k + j + ( m >> 1 ) ] = u - t;
                                w = w * wm;
                        }
                }
        }
        if ( DFT == -1 )
                for ( int i = 0; i < len; i++ )
                        A[ i ].real /= len, A[ i ].image /= len;
        for ( int i = 0; i < len; i++ )
                a[ i ] = A[ i ];
        return;
}

char numA[ 50010 ], numB[ 50010 ];
Complex a[ 140000 ], b[ 140000 ];
int ans[ 140000 ];
int main () {
        while ( ~scanf ( "%s", numA ) ) {
                int lenA = strlen ( numA );
                int sa = 0;             //lenA有多少位好吗
                while ( ( 1 << sa ) < lenA )
                        sa++;

                scanf ( "%s", numB );
                int lenB = strlen ( numB );
                int sb = 0;            //lenB有多少位
                while ( ( 1 << sb ) < lenB )
                        sb++;
                    //计算模板里的len,相当于算出A和B中最多有多少位的二次幂( FFT 深度 = lg(len))
                int len = ( 1 << ( max ( sa, sb ) + 1 ) );

                //字符串转化为整数
                for ( int i = 0; i < len; i++ ) {
                        if ( i < lenA )
                                a[ i ] = Complex ( numA[ lenA - i - 1 ] - '0', 0 );
                        else
                                a[ i ] = Complex ( 0, 0 );
                        if ( i < lenB )
                                b[ i ] = Complex ( numB[ lenB - i - 1 ] - '0', 0 );
                        else
                                b[ i ] = Complex ( 0, 0 );
                }

                //正变换求值
                IterativeFFT ( a, len, 1 );
                IterativeFFT ( b, len, 1 );

                //计算A*B
                for ( int i = 0; i < len; i++ )
                        a[ i ] = a[ i ] * b[ i ];

                //反变换得到C的系数
                IterativeFFT ( a, len, -1 );

                // 复数变整数????懵逼.jpg
                 for ( int i = 0; i < len; i++ )
                        ans[ i ] = (int)( a[ i ].real + 0.5 );


                // 进位
                for ( int i = 0; i < len - 1; i++ ) {
                        ans[ i + 1 ] += ans[ i ] / 10;
                        ans[ i ] %= 10;
                }

                bool flag = 0;

               //输出
                for ( int i = len - 1; i >= 0; i-- ) {
                        if ( ans[ i ] )
                                printf ( "%d", ans[ i ] ), flag = 1;
                        else if ( flag || i == 0 )
                                printf ( "0" );
                }
                putchar ( '\n' );
        }
        return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值