zoukankan      html  css  js  c++  java
  • 【CodeVS 3123】高精度练习之超大整数乘法 &【BZOJ 2197】FFT快速傅立叶

    第一次写法法塔,,,感到威力无穷啊

    看了一上午算导就当我看懂了?PS:要是机房里能有个清净的看书环境就好了

    FFT主要是用了巧妙的复数单位根,复数单位根在复平面上的对称性使得快速傅立叶变换的时间复杂度空降为O(nlogn)←个人的愚蠢理解请随意吐槽

    具体的我就不说了,算导上都说得很清楚,说得好像有人会听我说什么似的

    模板在这里↓

    CodeVS 3123:

    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N = 1E6 + 3;
    const double Pi = acos(- 1.0);
    struct cp {
    	double r, i;
    	cp(double _r = 0.0, double _i = 0.0) : r(_r), i(_i) {}
    	cp operator + (const cp &x) const {return cp(r + x.r, i + x.i);}
    	cp operator - (const cp &x) const {return cp(r - x.r, i - x.i);}
    	cp operator * (const cp &x) const {return cp(r * x.r - i * x.i, r * x.i + i * x.r);}
    };
    char s[N];
    int rev[N];
    cp A[N];
    void DFT(cp *a, int n, int flag) {
    	for(int i = 0; i < n; ++i) A[rev[i]] = a[i];
    	for(int i = 0; i < n; ++i) a[i] = A[i];
    	for(int m = 2, mid; m <= n; m <<= 1) {
    		cp wn(cos(2.0 * Pi / m * flag), sin(2.0 * Pi / m * flag));
    		mid = m >> 1;
    		for(int i = 0; i < n; i += m) {
    			cp w(1.0);
    			for(int j = 0; j < mid; ++j) {
    				cp u = a[i + j + mid] * w, t = a[i + j];
    				a[i + j] = t + u;
    				a[i + j + mid] = t - u;
    				w = w * wn;
    			}
    		}
    	}
    	if (flag == -1)
    		for(int i = 0; i < n; ++i)
    			a[i].r /= n;
    }
    
    void in(cp *a, int &n) {
    	scanf("%s", s);
    	n = strlen(s);
    	for(int i = 0; i < n; ++i)
    		a[i].r = s[n - i - 1] - '0';
    }
    void init(int &n) {
    	int k = 1, L = 0;
    	for(; k < n; k <<= 1, ++L);
    	n = k;
    	for(int i = 0; i < n; ++i) {
    		int t = i, ret = 0;
    		for(int j = 0; j < L; ++j)
    			ret <<= 1, ret |= (t & 1), t >>= 1;
    		rev[i] = ret;
    	}
    }
    cp a[N], b[N];
    int len = -1, n, ans[N];
    void FFT() {
    	DFT(a, len, 1); DFT(b, len, 1);
    	for(int i = 0; i < len; ++i)
    		a[i] = a[i] * b[i];
    	DFT(a, len, -1);
    }
    int main() {
    	in(a, n); len += n;
    	in(b, n); len += n;
    	init(len);
    	FFT();
    	for(int i = 0; i < len; ++i)
    		ans[i] = (int) (a[i].r + 0.5);
    	for(int i = 0; i < len; ++i)
    		ans[i + 1] += ans[i] / 10, ans[i] %= 10;
    	for(++len; ans[len] == 0 && len > 0; --len);
    	for(int i = len; i >= 0; --i)
    		printf("%d", ans[i]);
    	puts("");
    	return 0;
    }
    

    BZOJ 2197顺便水一水~:

    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N = 1E6 + 3;
    const double Pi = acos(- 1.0);
    struct cp {
    	double r, i;
    	cp(double _r = 0.0, double _i = 0.0) : r(_r), i(_i) {}
    	cp operator + (const cp &x) const {return cp(r + x.r, i + x.i);}
    	cp operator - (const cp &x) const {return cp(r - x.r, i - x.i);}
    	cp operator * (const cp &x) const {return cp(r * x.r - i * x.i, r * x.i + i * x.r);}
    };
    char s[N];
    int rev[N];
    cp A[N];
    void DFT(cp *a, int n, int flag) {
    	for(int i = 0; i < n; ++i) A[rev[i]] = a[i];
    	for(int i = 0; i < n; ++i) a[i] = A[i];
    	for(int m = 2, mid; m <= n; m <<= 1) {
    		cp wn(cos(2.0 * Pi / m * flag), sin(2.0 * Pi / m * flag));
    		mid = m >> 1;
    		for(int i = 0; i < n; i += m) {
    			cp w(1.0);
    			for(int j = 0; j < mid; ++j) {
    				cp u = a[i + j + mid] * w, t = a[i + j];
    				a[i + j] = t + u;
    				a[i + j + mid] = t - u;
    				w = w * wn;
    			}
    		}
    	}
    	if (flag == -1)
    		for(int i = 0; i < n; ++i)
    			a[i].r /= n;
    }
    
    void in(cp *a, int &n) {
    	scanf("%s", s);
    	n = strlen(s);
    	for(int i = 0; i < n; ++i)
    		a[i].r = s[n - i - 1] - '0';
    }
    void init(int &n) {
    	int k = 1, L = 0;
    	for(; k < n; k <<= 1, ++L);
    	n = k;
    	for(int i = 0; i < n; ++i) {
    		int t = i, ret = 0;
    		for(int j = 0; j < L; ++j)
    			ret <<= 1, ret |= (t & 1), t >>= 1;
    		rev[i] = ret;
    	}
    }
    cp a[N], b[N];
    int len = -1, n, ans[N];
    void FFT() {
    	DFT(a, len, 1); DFT(b, len, 1);
    	for(int i = 0; i < len; ++i)
    		a[i] = a[i] * b[i];
    	DFT(a, len, -1);
    }
    int main() {
    	scanf("%d
    ", &len); len = (len << 1) - 1;
    	in(a, n);
    	in(b, n);
    	init(len);
    	FFT();
    	for(int i = 0; i < len; ++i)
    		ans[i] = (int) (a[i].r + 0.5);
    	for(int i = 0; i < len; ++i)
    		ans[i + 1] += ans[i] / 10, ans[i] %= 10;
    	for(++len; ans[len] == 0 && len > 0; --len);
    	for(int i = len; i >= 0; --i)
    		printf("%d", ans[i]);
    	puts("");
    	return 0;
    }
    

    高一下半学期开学前的晚上就在看这个东西,拖到现在才理解,累啊~

  • 相关阅读:
    2008年总结
    感触
    24105
    事情总喜欢蜂拥而至
    最后的稻草
    什么叫服务
    sigh,终于submit了
    在工作和生活的狭缝中生存着
    不应该,不应该
    ren 人 认 忍 韧 仁
  • 原文地址:https://www.cnblogs.com/abclzr/p/5431774.html
Copyright © 2011-2022 走看看