zoukankan      html  css  js  c++  java
  • FFT版题 [51 Nod 1028] 大数乘法

    题目链接:51 Nod 传送门
    数的长度为10510^5,乘起来后最大长度为2×1052 imes10^5
    由于FFT需要把长度开到22的次幂,所以不能只开到2×1052 imes10^5,会TLE(卡了好久,还以为是要压位)

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    const int MAXN = 400005;//!!!
    const double Pi = acos(-1.0);
    
    struct complex
    {
    	double r, i;
    	complex(double _r=0, double _i=0):r(_r), i(_i){}
    	complex operator +(const complex &t)const
    	{
    		return complex(r + t.r, i + t.i);
    	}
    	complex operator -(const complex &t)const
    	{
    		return complex(r - t.r, i - t.i);
    	}
    	complex operator *(const complex &t)const
    	{
    		return complex(r*t.r - i*t.i, r*t.i + t.r*i);
    	}
    }a1[MAXN], a2[MAXN], w, wn;
    char s1[MAXN], s2[MAXN];
    int n, len1, len2, ans[MAXN];
    
    inline void change(complex arr[], int len)
    {
    	for(int i = 1, j = len/2, k; i < len-1; ++i)
    	{
    		if(i < j) swap(arr[i], arr[j]);
    		for(k = len/2; k <= j; j-=k, k>>=1);
    		j += k;
    	}
    }
    
    inline void fft(complex arr[], int len, int flg)
    {
    	for(int i = 2; i <= len; i<<=1)
    	{
    		wn = complex(cos(Pi*flg*2/i), sin(Pi*flg*2/i));
    		for(int j = 0; j < len; j+=i)
    		{
    			w = complex(1, 0);
    			for(int k = j; k < j + i/2; ++k)
    			{
    				complex u = w * arr[k + i/2];
    				complex v = arr[k];
    				arr[k] = v + u;
    				arr[k + i/2] = v - u;
    				w = w * wn;
    			}
    		}
    	}
    	if(flg == -1)
    		for(int i = 0; i < len; ++i)
    			arr[i].r /= len;
    }
    
    inline void FFT(complex arr[], int len, int flg)
    {
    	change(arr, len);
    	fft(arr, len, flg);
    }
    
    int main()
    {
    	scanf("%s", s1), len1 = strlen(s1);
    	scanf("%s", s2), len2 = strlen(s2);
    	int len = len1 + len2;
    	for(n = 1; n < len; n<<=1);
    
    	for(int i = 0; i < len1; ++i) a1[i] = complex((double)(s1[i] - '0'), 0);
    	for(int i = len1; i < n; ++i) a1[i] = complex();
    	FFT(a1, n, 1);
    
    	for(int i = 0; i < len2; ++i) a2[i] = complex((double)(s2[i] - '0'), 0);
    	for(int i = len2; i < n; ++i) a2[i] = complex();
    	FFT(a2, n, 1);
    	
    	for(int i = 0; i < n; ++i) a2[i] = a1[i] * a2[i];
    	FFT(a2, n, -1);
    	
    	for(int i = 0; i < len1+len2-1; ++i)
    		ans[i] = (int)(a2[i].r + 0.5);
    	
    	for(int i = len1+len2-2; i; --i)
    	{
    		ans[i-1] += ans[i]/10;
    		ans[i] %= 10;
    	}
    	int i;
    	for(i = 0; !ans[i] && i < len1+len2-1; ++i);
    	if(i == len1+len2-1) putchar('0');
    	else while(i < len1+len2-1) printf("%d",ans[i++]); //此处不能用putchar
    	//因为我ans[0]没有向前进位,所以要用%d输出
    	putchar(10);
    }
    
    
  • 相关阅读:
    VB几种函数参数传递方法,Variant,数组,Optional,ParamArray
    一些 Windows 系统不常见的 鼠标光标常数
    加载MSCOMCTL.OCX错误处理的几个关键
    如何快速掌握一门技术
    《将博客搬至CSDN》
    日期小demo
    iOS崩溃解决记录
    Swift基础语法
    iOS端APP切图命名规范大全
    PHP案例:学生信息管理系统
  • 原文地址:https://www.cnblogs.com/Orz-IE/p/12039453.html
Copyright © 2011-2022 走看看