zoukankan      html  css  js  c++  java
  • BZOJ-2179 FFT快速傅立叶

    丧心病狂的多项式乘法。。

    FFT模版题。。

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <iostream>
    #include <cctype>
    #include <complex>
    #define rep(i, l, r) for(int i=l; i<=r; i++)
    #define down(i, l, r) for(int i=l; i>=r; i--)
    #define cd complex <double>
    #define PI acos(0.0)*2.0
    #define ll long long
    #define base 10000
    #define maxn 50009
    using namespace std;
    inline int read()
    {
    	int x=0, f=1; char ch=getchar();
    	while (!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
    	while (isdigit(ch)) x=x*10+ch-'0', ch=getchar();
    	return x*f;
    }
    cd a[maxn], b[maxn], c[maxn], A[maxn];
    ll ans[maxn];
    int n, m, len, n1[maxn], n2[maxn], s[maxn], ansn=0;
    char num[maxn];
    void fft(cd *a, bool flag)
    {
    	rep(i, 0, n-1) s[i]=0;
    	for(int i=1, j=n; i<n; i*=2, j/=2) rep(h, j/2, j-1) s[h]+=i;
    	for(int i=1; i<n; i*=2) rep(j, 0, i-1) s[j+i]+=s[j];
    	rep(i, 0, n-1) A[i]=a[s[i]];
    	double pi=flag?PI:-PI;
    	for(int step=1; step<n; step*=2)
    	{
    		cd e=exp(cd(0, 2.0*pi/double(step*2))), w=cd(1, 0);
    		for(int pos=0; pos<step; ++pos, w*=e) 
    			for(int i=pos; i<n; i+=step*2)
    			{
    				cd ret=A[i], rec=w*A[i+step];
    				A[i]=ret+rec, A[i+step]=ret-rec;
    			}
    	}
    	if (!flag) rep(i, 0, n-1) A[i]/=n;
    	rep(i, 0, n-1) a[i]=A[i];
    }
    int main()
    {
    	m=read(); len=(m-1)/4+1;
    	scanf("%s", num);
    	rep(i, 0, m-1) n1[(m-1-i)/4]=n1[(m-1-i)/4]*10+num[i]-'0';
    	scanf("%s", num);
    	rep(i, 0, m-1) n2[(m-1-i)/4]=n2[(m-1-i)/4]*10+num[i]-'0';
    	n=1; m=len*2; while (n<m) n*=2;
    	rep(i, 0, n-1) a[i]=cd(n1[i], 0); fft(a, true);
    	rep(i, 0, n-1) b[i]=cd(n2[i], 0); fft(b, true);
    	rep(i, 0, n-1) c[i]=a[i]*b[i]; fft(c, false);
    	rep(i, 0, n-1) ans[i]=(ll)(c[i].real()+0.5);
    	rep(i, 0, n-1) ans[i+1]+=ans[i]/base, ans[i]%=base;
    	ansn=n; while (ansn>0 && !ans[ansn]) ansn--;
    	printf("%lld", ans[ansn]);
    	down(i, ansn-1, 0)
    		if (ans[i]>=1000) printf("%lld", ans[i]);
    		else if (ans[i]>=100) printf("0%lld", ans[i]);
    		else if (ans[i]>=10) printf("00%lld", ans[i]);
    		else printf("000%lld", ans[i]);
    	printf("
    ");
    	return 0;
    }
  • 相关阅读:
    SSH综合练习-仓库管理系统-第二天
    SSH综合练习-第1天
    Spring第三天
    Spring第二天
    Spring第一天
    【pandas】pandas.Series.str.split()---字符串分割
    【剑指offer】和为s的两个数字
    【剑指offer】数组中只出现一次的数字
    【剑指offer】输入一颗二叉树的根节点,求二叉树的深度,C++实现
    【剑指offer】输入一颗二叉树的根节点,判断是不是平衡二叉树,C++实现
  • 原文地址:https://www.cnblogs.com/NanoApe/p/4479383.html
Copyright © 2011-2022 走看看