• 【luogu P1919】【模板】A*B Problem升级版(FFT快速傅里叶)


    【模板】A*B Problem升级版(FFT快速傅里叶)

    题目链接:luogu P1919

    题目大意

    给你 a,b 两个数,要你求 a*b。
    数很大。

    思路

    就是把每一位当做一项,然后做 FFT,然后不要忘记进位就可以了。
    (记得倒叙储存)

    代码

    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    
    using namespace std;
    
    struct complex {
    	double x, y;
    	complex (double X = 0, double Y = 0) {x = X; y = Y;}
    }a[4000005], b[4000005];
    char as[1000001], bs[1000001];
    int an, bn, limit, ln, ann[4000001], ans[4000005];
    double Pi = acos(-1.0);
    
    complex operator +(complex x, complex y) {
    	return complex(x.x + y.x, x.y + y.y);
    }
    
    complex operator -(complex x, complex y) {
    	return complex(x.x - y.x, x.y - y.y);
    }
    
    complex operator *(complex x, complex y) {
    	return complex(x.x * y.x - x.y * y.y, x.x * y.y + x.y * y.x);
    }
    
    void FFT(complex *now, int op) {
    	for (int i = 0; i < limit; i++)
    		if (i > ann[i]) swap(now[i], now[ann[i]]);
    	
    	for (int mid = 1; mid < limit; mid <<= 1) {
    		complex Wn(cos(Pi / mid), op * sin(Pi / mid));
    		for (int R = (mid << 1), j = 0; j < limit; j += R) {
    			complex w(1, 0);
    			for (int k = 0; k < mid; k++, w = w * Wn) {
    				complex x = now[j + k], y = w * now[j + mid + k];
    				now[j + k] = x + y; now[j + mid + k] = x - y;
    			}
    		}
    	}
    }
    
    int main() {
    	scanf("%s
    %s", &as, &bs);
    	an = strlen(as) - 1; bn = strlen(bs) - 1;
    	
    	for (int i = 0; i <= an; i++)//倒叙储存
    		a[an - i].x = as[i] - '0';
    	for (int i = 0; i <= bn; i++)
    		b[bn - i].x = bs[i] - '0';
    	
    	limit = 1;
    	while (limit < an + bn) {
    		limit <<= 1;
    		ln++;
    	}
    	
    	for (int i = 0; i < limit; i++)
    		ann[i] = (ann[i >> 1] >> 1) | ((i & 1) << (ln - 1));
    	
    	FFT(a, 1); FFT(b, 1);
    	for (int i = 0; i <= limit; i++)
    		a[i] = a[i] * b[i];
    	FFT(a, -1);
    	
    	for (int i = 0; i <= limit; i++) {
    		ans[i] += (int)(a[i].x / limit + 0.5);
    		if (ans[i] >= 10) {//进位
    			ans[i + 1] += ans[i] / 10;
    			ans[i] %= 10;
    			if (i == limit) limit++;
    		}
    	}
    	
    	while (limit && !ans[limit]) limit--;
    	for (int i = 0; i <= limit; i++)
    		printf("%d", ans[limit - i]);
    	
    	return 0;
    }
    
  • 相关阅读:
    scheme中的fold-left和fold-right
    test
    2018.4.24-ml笔记(多元线性回归)
    2018.4.23-ml笔记(线性回归、梯度下降)
    springboot shiro开启注释
    Spring杂记BeanFactory之getBean方法
    docker搭建nginx+springboot集群
    springboot属性注入转化为对象
    mac下nginx搭建
    mybatis随笔五之Executor
  • 原文地址:https://www.cnblogs.com/Sakura-TJH/p/luogu_P1919.html
Copyright © 2020-2023  润新知