zoukankan      html  css  js  c++  java
  • Luogu3803 【模板】多项式乘法(FFT)

    为什么我这么弱


    其实FFT也挺水的,一点数学基础加上细心即可。细节·技巧挺多。

    递归

    在TLE的边缘苦苦挣扎

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #define R(a,b,c) for(register int  a = (b); a <= (c); ++ a)
    #define nR(a,b,c) for(register int  a = (b); a >= (c); -- a)
    #define Max(a,b) ((a) > (b) ? (a) : (b))
    #define Min(a,b) ((a) < (b) ? (a) : (b))
    #define Fill(a,b) memset(a, b, sizeof(a))
    #define Abs(a) ((a) < 0 ? -(a) : (a))
    #define Swap(a,b) a^=b^=a^=b
    #define ll long long
    
    //#define ON_DEBUG
    
    #ifdef ON_DEBUG
    
    #define D_e_Line printf("
    
    ----------
    
    ")
    #define D_e(x)  cout << #x << " = " << x << endl
    #define Pause() system("pause")
    #define FileOpen() freopen("in.txt","r",stdin);
    
    #else
    
    #define D_e_Line ;
    #define D_e(x)  ;
    #define Pause() ;
    #define FileOpen() ;
    
    #endif
    
    struct ios{
        template<typename ATP>ios& operator >> (ATP &x){
            x = 0; int f = 1; char c;
            for(c = getchar(); c < '0' || c > '9'; c = getchar()) if(c == '-')  f = -1;
            while(c >= '0' && c <= '9') x = x * 10 + (c ^ '0'), c = getchar();
            x*= f;
            return *this;
        }
    }io;
    using namespace std;
    
    const int N = 4000007; // how much should I open QAQ ?
    const double pi = acos(-1.0);
    
    struct Complex{
    	double x, y;
    	Complex (double xx = 0, double yy = 0) {x = xx, y = yy;}
    	
    	Complex operator + (Complex b){ return Complex(x + b.x, y + b.y); }
    	Complex operator - (Complex b){ return Complex(x - b.x, y - b.y); }
    	Complex operator * (Complex b){ return Complex(x * b.x - y * b.y, x * b.y + y * b.x); }	
    }a[N], b[N];
    
    inline void FFT(int limit, Complex *a, int opt){
    	if(limit == 1) return;
    	Complex a1[(limit >> 1) + 3], a2[(limit >> 1) + 3];
    	for(register int i = 0; i <= limit; i += 2){
    		a1[i >> 1] = a[i];
    		a2[i >> 1] = a[i + 1];
    	}
    	FFT(limit >> 1, a1, opt);
    	FFT(limit >> 1, a2, opt);
    	Complex Wn = Complex( cos(2.0 * pi / limit), opt * sin(2.0 * pi / limit));
    	Complex w = Complex( 1, 0);
    	R(i,0,(limit >> 1) - 1){ // be careful, do not write 'R(i,0,(limit >> 1))'
    		a[i] = a1[i] + w * a2[i];
    		a[i + (limit >> 1)] = a1[i] - w * a2[i];
    		w = w * Wn;
    	}
    }
    
    int main(){
    	int n, m;
    	io >> n >> m;
    	R(i,0,n) io >> a[i].x;
    	R(i,0,m) io >> b[i].x;
    
    	int limit;
    	for(limit = 1; limit <= n + m; limit <<= 1);
    	
    	FFT(limit, a, 1);
    	FFT(limit, b, 1); // coefficient changes to point value
    	
    	R(i,0,limit){
    		a[i] = a[i] * b[i];
    	}
    	
    	FFT(limit, a, -1); // point value changes to coefficient
    	
    	R(i,0,n + m){
    		printf("%d ", (int)(a[i].x / limit + 0.5)); // ans should divide limit
    	}
    	
    	return 0;
    }
    

    迭代

    快得飞起 *^* /

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #define R(a,b,c) for(register int  a = (b); a <= (c); ++ a)
    #define nR(a,b,c) for(register int  a = (b); a >= (c); -- a)
    #define Max(a,b) ((a) > (b) ? (a) : (b))
    #define Min(a,b) ((a) < (b) ? (a) : (b))
    #define Fill(a,b) memset(a, b, sizeof(a))
    #define Abs(a) ((a) < 0 ? -(a) : (a))
    #define Swap(a,b) a^=b^=a^=b
    #define ll long long
    
    //#define ON_DEBUG
    
    #ifdef ON_DEBUG
    
    #define D_e_Line printf("
    
    ----------
    
    ")
    #define D_e(x)  cout << #x << " = " << x << endl
    #define Pause() system("pause")
    #define FileOpen() freopen("in.txt","r",stdin);
    
    #else
    
    #define D_e_Line ;
    #define D_e(x)  ;
    #define Pause() ;
    #define FileOpen() ;
    
    #endif
    
    struct ios{
        template<typename ATP>ios& operator >> (ATP &x){
            x = 0; int f = 1; char c;
            for(c = getchar(); c < '0' || c > '9'; c = getchar()) if(c == '-')  f = -1;
            while(c >= '0' && c <= '9') x = x * 10 + (c ^ '0'), c = getchar();
            x*= f;
            return *this;
        }
    }io;
    using namespace std;
    
    const int N = 4000007; // how much should I open QAQ ? // Oh, I undersand ! It's influenced by 'limit'
    const double pi = acos(-1.0);
    
    struct Complex{
    	double x, y;
    	Complex (double xx = 0, double yy = 0) {x = xx, y = yy;}
    	
    	Complex operator + (Complex b){ return Complex(x + b.x, y + b.y); }
    	Complex operator - (Complex b){ return Complex(x - b.x, y - b.y); }
    	Complex operator * (Complex b){ return Complex(x * b.x - y * b.y, x * b.y + y * b.x); }	
    }a[N], b[N];
    
    int r[N];
    
    inline void FFT(int limit, Complex *a, int opt){
        R(i,0,limit - 1)
        	if(i < r[i])
        		swap(a[i], a[r[i]]);
        for(register int mid = 1; mid < limit; mid <<= 1){
        	Complex Wn( cos(pi / mid), opt * sin(pi / mid));
        	int len = mid << 1;
        	for(register int j = 0; j < limit; j += len){
        		Complex w( 1, 0);
        		R(k,0,mid - 1){
        			Complex x = a[j + k], y = w * a[j + mid + k];
        			a[j + k] = x + y;
        			a[j + mid + k] = x - y;
        			w = w * Wn;
        		}
        	}
        }
    }
    
    int main(){
    	FileOpen();
    	int n, m;
    	io >> n >> m;
    	R(i,0,n) io >> a[i].x;
    	R(i,0,m) io >> b[i].x;
    
    	int limit = 1, len = 0;
    	while(limit <= n + m){
    		limit <<= 1;
    		++len;
    	}
    	
        R(i,0,limit - 1){
        	r[i] = (r[i >> 1] >> 1) | ((i & 1) << (len - 1));
        }
            
    	
    	FFT(limit, a, 1);
    	FFT(limit, b, 1); // coefficient changes to point value
    	
    	R(i,0,limit){
    		a[i] = a[i] * b[i];
    	}
    	
    	FFT(limit, a, -1); // point value changes to coefficient
    	
    	R(i,0,n + m){
    		printf("%d ", (int)(a[i].x / limit + 0.5)); // ans should divide limit
    	}
    	
    	return 0;
    }
    

  • 相关阅读:
    链表
    链式学习法:提升技术深度
    数组
    写点什么
    7 天掌握算法面试必考知识点: 作业安排及如何提交
    创建Mac OS root账户
    正则表达式匹配及替换
    Xcode 10 之New Build System & Legacy Build System 旧版构建系统
    性能指标:TPS、QPS、RT、吞吐量
    Objective-C和Swift语言特性
  • 原文地址:https://www.cnblogs.com/bingoyes/p/11225225.html
Copyright © 2011-2022 走看看