洛谷-1919 【模板】A*B Problem升级版(FFT快速傅里叶,常数小)

题目描述
给出两个n位10进制整数x和y,你需要计算xy。
输入输出格式
输入格式:
第一行一个正整数n。 第二行描述一个位数为n的正整数x。 第三行描述一个位数为n的正整数y。
输出格式:
输出一行,即x
y的结果。(注意判断前导0)

输入输出样例
输入样例#1:
1
3
4

输出样例#1:
12

说明
数据范围:
n<=60000
来源:bzoj2179
本题数据为洛谷自造数据,使用CYaRon耗时5分钟完成数据制作。

#include <cmath>
#include <cstdio>
#include <iostream>
#define MAXN 200100

using namespace std ;
char s1[MAXN], s2[MAXN] ;
int N, M, K, res = 0, ans[MAXN], AA, BB ;
int i, j, k, l, Lim = 1, L, R[MAXN] ;
const double Pi = acos(-1.0) ;
struct node{
    double x, y ;
    node (double xx = 0, double yy = 0){
        x = xx, y = yy ;
    }
}A[MAXN], B[MAXN] ;
node operator * (node J, node Q){
    return node(J.x * Q.x - J.y * Q.y , J.x * Q.y + J.y * Q.x);
}
node operator + (node J, node Q){
    return node(J.x + Q.x , J.y + Q.y);
}
node operator - (node J, node Q){
    return node(J.x - Q.x , J.y - Q.y );
}
void FFT(node *J, double flag){
    for(i = 0; i < Lim; i ++)
        if(i < R[i]) swap(J[i], J[R[i]]) ;
    for(j = 1; j < Lim; j <<= 1){
        node T(cos(Pi / j), flag * sin(Pi / j)) ;
        for(k = 0; k < Lim; k += (j << 1) ){
            node t(1, 0) ;
            for(l = 0 ; l < j; l ++, t = t * T){
                node Nx = J[k + l], Ny = t * J[k + j + l] ;
                J[k + l] = Nx + Ny ;
                J[k + j + l] = Nx - Ny ;
            }
        }
    }
}
int main(){
    scanf("%d",&N);
    scanf("%s%s", s1, s2) ;
    for(i = N - 1; i >= 0; i --) A[AA ++].x = s1[i] - 48;
    for(i = N - 1; i >= 0; i --) B[BB ++].x = s2[i] - 48;
    while(Lim < N + N ) Lim <<= 1, L ++ ;
    for(i = 0; i <= Lim; i ++ ) R[i] = (R[i >> 1] >> 1) | ((i & 1) << (L - 1));
    FFT(A, 1), FFT(B, 1) ;
    for(i = 0; i <= Lim; i ++) A[i] = A[i] * B[i] ;
    FFT(A, -1) ;
    for(i = 0; i <= Lim; i++) {
        ans[i] += (int) (A[i].x / Lim + 0.5) ;
        if(ans[i] >= 10)
            ans[i + 1] += ans[i] / 10, ans[i] %= 10, Lim += (i == Lim);
    }
    while(!ans[Lim] && Lim >= 1) Lim -- ;
    Lim ++ ;
    while( -- Lim >= 0) cout << ans[Lim] ;
    return 0 ;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值