多項式乘法與離散傅里葉變換


多項式的表示方法

系數表示法:

$$f(x)=a_0+a_1x+a_2x^2+\cdots+a_nx^n$$

點值表示法:

$$f(x)=\{(x_0,f(x_0)),(x_1,f(x_1)),(x_2,f(x_2)),\cdots,(x_n,f(x_n))\}$$

多項式乘法與DFT

設我們已知兩個點值表示法的多項式$f(x),g(x)$:

$$f(x)=\{(x_0,f(x_0)),(x_1,f(x_1)),(x_2,f(x_2)),\cdots,(x_n,f(x_n))\}$$

$$g(x)=\{(x_0,g(x_0)),(x_1,g(x_1)),(x_2,g(x_2)),\cdots,(x_n,g(x_n))\}$$

設兩個多項式相乘和結果是$h(x)$:

$$h(x)=\{(x_0,f(x_0)g(x_0)),(x_1,f(x_1)g(x_1)),(x_2,f(x_2)g(x_2)),\cdots,(x_n,f(x_n)g(x_n))\}$$

是不是感覺多項式乘法能$O(n)$過。
你想多了。。。
如何將系數轉點值?
朴素的系數轉點值叫做DFT(離散傅里葉變換),點值轉系數叫做IDFT(離散傅里葉逆變換),計算式DFT,IDFT仍然需要$O(n^2)$。
難道就沒有其他辦法了嗎?
當然有。FFT和IFFT閃亮登場,我們只要$O(n\log(n))$,就可以完成雙方的轉換。

單位復根

事實上,對於多項式系數轉點值,我們可以隨意取n個不同的x,但這種暴力法太慢。但我們可以取一些神奇的點,將滿足$\omega ^n=1$的值作為帶入的點。這就是離散傅里葉變換的神奇之處了,取的點不是實數,而是復數。

求解$\omega ^n=1$

對於所有的解都可以在下圖的圓上得到:

以$n=8$為例,即$\omega ^8=1$

將一個圓分成8份,我們可以得到8個解:$\omega _8^0,\omega _8^1,\omega _8^2,\omega _8^3,\omega _8^4,\omega _8^5,\omega _8^6,\omega _8^7$

即:$$\omega _n^k=\cos{\frac{2\pi }{n}k}+i\sin{\frac{2\pi }{n}k}$$

性質:

$(1)~~\omega _{an}^{ak}=\omega _n^k$

$(2)~~\omega _n^{k-\frac n2}=-\omega _n^k$

$(3)~~\omega _n^k=\omega _n^{k\%n}$

$(4)~~(\omega _n^k)^p=\omega _n^{kp}$

FFT(快速傅里葉變換)

我們以多項式$f(x)=a_0+a_1x+a_2x^2+a_3x^3+a_4x^4+a_5x^5+a_6x^6+a_7x^7$為例:

$\begin{align*} f(x)&=a_0+a_1x+a_2x^2+a_3x^3+a_4x^4+a_5x^5+a_6x^6+a_7x^7 \\ &=a_0+a_2x^2+a_4x^4+a_6x^6+x(a_1+a_3x^2+a_5x^4+a_7x^6) \end{align*}$

$令A^{[0]}(x)=a_0+a_2x+a_4x^2+a_6x^3,A^{[1]}(x)=a_1+a_3x+a_5x^2+a_7x^3$

$則f(x)=A^{[0]}(x^2)+xA^{[1]}(x^2)$

$\begin{align*} &f(\omega _8^0)=A^{[0]}(\omega _8^0)+\omega _8^0A^{[1]}(\omega _8^0) =A^{[0]}(\omega _4^0)+\omega _8^0A^{[1]}(\omega _4^0) \\ &f(\omega _8^1)=A^{[0]}(\omega _8^2)+\omega _8^1A^{[1]}(\omega _8^2) =A^{[0]}(\omega _4^1)+\omega _8^1A^{[1]}(\omega _4^1) \\ &f(\omega _8^2)=A^{[0]}(\omega _8^4)+\omega _8^2A^{[1]}(\omega _8^4) =A^{[0]}(\omega _4^2)+\omega _8^2A^{[1]}(\omega _4^2) \\ &f(\omega _8^3)=A^{[0]}(\omega _8^6)+\omega _8^3A^{[1]}(\omega _8^6) =A^{[0]}(\omega _4^3)+\omega _8^3A^{[1]}(\omega _4^3) \\ &f(\omega _8^4)=A^{[0]}(\omega _8^8)+\omega _8^4A^{[1]}(\omega _8^8) =A^{[0]}(\omega _4^0)-\omega _8^0A^{[1]}(\omega _4^0) \\ &f(\omega _8^5)=A^{[0]}(\omega _8^{10})+\omega _8^5A^{[1]}(\omega _8^{10})=A^{[0]}(\omega _4^1)-\omega _8^1A^{[1]}(\omega _4^1) \\ &f(\omega _8^6)=A^{[0]}(\omega _8^{12})+\omega _8^6A^{[1]}(\omega _8^{12})=A^{[0]}(\omega _4^2)-\omega _8^2A^{[1]}(\omega _4^2) \\ &f(\omega _8^7)=A^{[0]}(\omega _8^{14})+\omega _8^7A^{[1]}(\omega _8^{14})=A^{[0]}(\omega _4^3)-\omega _8^3A^{[1]}(\omega _4^3) \end{align*}$

$\begin{align*} A^{[0]}(x)&=a_0+a_2x+a_4x^2+a_6x^3 \\ &=a_0+a_4x^2+x(a_2+a_6x^2) \end{align*}$

令$B^{[0]}(x)=a_0+a_4x,B^{[1]}(x)=a_2+a_6x$

則$A^{[0]}(x)=B^{[0]}(x^2)+xB^{[1]}(x^2)$

$\begin{align*} &A^{[0]}(\omega _4^0)=B^{[0]}(\omega _4^0)+\omega _4^0B^{[1]}(\omega _4^0)=B^{[0]}(\omega _2^0)+\omega _4^0B^{[1]}(\omega _2^0) \\ &A^{[0]}(\omega _4^1)=B^{[0]}(\omega _4^2)+\omega _4^1B^{[1]}(\omega _4^2)=B^{[0]}(\omega _2^1)+\omega _4^1B^{[1]}(\omega _2^1) \\ &A^{[0]}(\omega _4^2)=B^{[0]}(\omega _4^4)+\omega _4^2B^{[1]}(\omega _4^4)=B^{[0]}(\omega _2^0)-\omega _4^0B^{[1]}(\omega _2^0) \\ &A^{[0]}(\omega _4^3)=B^{[0]}(\omega _4^6)+\omega _4^3B^{[1]}(\omega _4^6)=B^{[0]}(\omega _2^1)-\omega _4^1B^{[1]}(\omega _2^1) \\ \end{align*}$

$\begin{align*} B^{[0]}(x)&=a_0+a_4x \\ &=a_0+xa_4 \end{align*}$

$\begin{align*} &B^{[0]}(\omega _2^0)=a_0+\omega _2^0 a_4 \\ &B^{[0]}(\omega _2^1)=a_0+\omega _2^1 a_4=a_0-\omega _2^0 a_4 \\ \end{align*}$

我只寫了二叉樹一直往左走的情況,全部情況如下圖

IFFT(快速傅里葉逆變換)

對於上面的方程組我們可以用矩陣來表示:

$$\begin{bmatrix} 1 & 1 & 1 & 1 & 1 & 1 & 1 & 1 \\ 1 & \omega_8^1 & \omega_8^2 & \omega_8^3 & \omega_8^4 & \omega_8^8 & \omega_8^6 & \omega_8^7 \\ 1 & \omega_8^2 & \omega_8^4 & \omega_8^6 & \omega_8^8 & \omega_8^{10} & \omega_8^{12} & \omega_8^{14} \\ 1 & \omega_8^3 & \omega_8^6 & \omega_8^9 & \omega_8^{12} & \omega_8^{15} & \omega_8^{18} & \omega_8^{21} \\ 1 & \omega_8^4 & \omega_8^8 & \omega_8^12 & \omega_8^{16} & \omega_8^{20} & \omega_8^{24} & \omega_8^{28} \\ 1 & \omega_8^5 & \omega_8^{10} & \omega_8^{15} & \omega_8^{20} & \omega_8^{25} & \omega_8^{30} & \omega_8^{35} \\ 1 & \omega_8^6 & \omega_8^{12} & \omega_8^{18} & \omega_8^{24} & \omega_8^{30} & \omega_8^{36} & \omega_8^{42} \\ 1 & \omega_8^7 & \omega_8^{14} & \omega_8^{21} & \omega_8^{28} & \omega_8^{35} & \omega_8^{42} & \omega_8^{49} \end{bmatrix} \begin{bmatrix} a_0 \\ a_1 \\ a_2 \\ a_3 \\ a_4 \\ a_5 \\ a_6 \\ a_7 \end{bmatrix} = \begin{bmatrix} f(\omega _8^0) \\ f(\omega _8^1) \\ f(\omega _8^2) \\ f(\omega _8^3) \\ f(\omega _8^4) \\ f(\omega _8^5) \\ f(\omega _8^7) \\ f(\omega _8^7) \end{bmatrix}$$

$$\begin{bmatrix} a_0 \\ a_1 \\ a_2 \\ a_3 \\ a_4 \\ a_5 \\ a_6 \\ a_7 \end{bmatrix} = \begin{bmatrix} 1 & 1 & 1 & 1 & 1 & 1 & 1 & 1 \\ 1 & \omega_8^1 & \omega_8^2 & \omega_8^3 & \omega_8^4 & \omega_8^8 & \omega_8^6 & \omega_8^7 \\ 1 & \omega_8^2 & \omega_8^4 & \omega_8^6 & \omega_8^8 & \omega_8^{10} & \omega_8^{12} & \omega_8^{14} \\ 1 & \omega_8^3 & \omega_8^6 & \omega_8^9 & \omega_8^{12} & \omega_8^{15} & \omega_8^{18} & \omega_8^{21} \\ 1 & \omega_8^4 & \omega_8^8 & \omega_8^12 & \omega_8^{16} & \omega_8^{20} & \omega_8^{24} & \omega_8^{28} \\ 1 & \omega_8^5 & \omega_8^{10} & \omega_8^{15} & \omega_8^{20} & \omega_8^{25} & \omega_8^{30} & \omega_8^{35} \\ 1 & \omega_8^6 & \omega_8^{12} & \omega_8^{18} & \omega_8^{24} & \omega_8^{30} & \omega_8^{36} & \omega_8^{42} \\ 1 & \omega_8^7 & \omega_8^{14} & \omega_8^{21} & \omega_8^{28} & \omega_8^{35} & \omega_8^{42} & \omega_8^{49} \end{bmatrix}^{-1} \begin{bmatrix} f(\omega _8^0) \\ f(\omega _8^1) \\ f(\omega _8^2) \\ f(\omega _8^3) \\ f(\omega _8^4) \\ f(\omega _8^5) \\ f(\omega _8^6) \\ f(\omega _8^7) \end{bmatrix} $$

看起來是不是像范德蒙德行列式。
我們只要能夠得到范德蒙德矩陣的逆,一切就解決了。
事實是,普通的范德蒙德矩陣求逆很麻煩。
但,在復數領域一切都變得簡單了呢。

矩陣求逆:

$$\begin{bmatrix} 1 & 1 & \cdots & 1 \\ 1 & \omega _n^1 & \cdots &\omega _n^{n-1} \\ \vdots & \vdots & & \vdots \\ 1 & \omega _n^{n-1} & \cdots & \omega _n^{(n-1)(n-1)} \end{bmatrix}^{-1} = \frac 1n \begin{bmatrix} 1 & 1 & \cdots & 1 \\ 1 & \omega _n^{-1} & \cdots &\omega _n^{-(n-1)} \\ \vdots & \vdots & & \vdots \\ 1 & \omega _n^{-(n-1)} & \cdots & \omega _n^{-(n-1)(n-1)} \end{bmatrix} $$

所以最后得到公式:

$$a(x)=f(\omega _8^0)+f(\omega _8^1)x^{1}+f(\omega _8^2)x^{2}+f(\omega _8^3)x^{3}+f(\omega _8^4)x^{4}+f(\omega _8^5)x^{5}+f(\omega _8^6)x^{6}+f(\omega _8^7)x^{7}$$

怎么感覺和最上面的$f(x)=a_0+a_1x+a_2x^2+a_3x^3+a_4x^4+a_5x^5+a_6x^6+a_7x^7$有幾分相似。
只是將點,相應的變成原來的共軛復數

$\begin{align*} a(x)&=f(\omega _8^0)+f(\omega _8^1)x^{1}+f(\omega _8^2)x^{2}+f(\omega _8^3)x^{3}+f(\omega _8^4)x^{4}+f(\omega _8^5)x^{5}+f(\omega _8^6)x^{6}+f(\omega _8^7)x^{7} \\ &=f(\omega _8^0)+f(\omega _8^2)x^2+f(\omega _8^4)x^4+f(\omega _8^6)x^6+x(f(\omega _8^1)+f(\omega _8^3)x^4+f(\omega _8^5)x^4+f(\omega _8^7)x^6) \end{align*}$

$令A^{[0]}(x)=f(\omega _8^0)+f(\omega _8^2)x+f(\omega _8^4)x^2+f(\omega _8^6)x^3,A^{[1]}(x)=f(\omega _8^1)+f(\omega _8^3)x+f(\omega _8^5)x^2+f(\omega _8^7)x^3$

$則a(x)=A^{[0]}(x^2)+xA^{[1]}(x^2)$

$\begin{align*} & a(\omega _8^0) =A^{[0]}(\omega _8^0) +\omega _8^0 A^{[1]}(\omega _8^0) =A^{[0]}(\omega _4^0)+\omega _8^0A^{[1]}(\omega _4^0) \\ & a(\omega _8^{-1})=A^{[0]}(\omega _8^{-2})+\omega _8^{-1}A^{[1]}(\omega _8^{-2})=A^{[0]}(\omega _4^{-1})+\omega _8^{-1}A^{[1]}(\omega _4^{-1}) \\ & a(\omega _8^{-2})=A^{[0]}(\omega _8^{-4})+\omega _8^{-2}A^{[1]}(\omega _8^{-4})=A^{[0]}(\omega _4^{-2})+\omega _8^{-2}A^{[1]}(\omega _4^{-2}) \\ & a(\omega _8^{-3})=A^{[0]}(\omega _8^{-6})+\omega _8^{-3}A^{[1]}(\omega _8^{-6})=A^{[0]}(\omega _4^{-3})+\omega _8^{-3}A^{[1]}(\omega _4^{-3}) \\ & a(\omega _8^{-4})=A^{[0]}(\omega _8^{-8})+\omega _8^{-4}A^{[1]}(\omega _8^{-8})=A^{[0]}(\omega _4^0)-\omega _8^0A^{[1]}(\omega _4^0) \\ & a(\omega _8^{-5})=A^{[0]}(\omega _8^{-10})+\omega _8^{-5}A^{[1]}(\omega _8^{-10})=A^{[0]}(\omega _4^{-1})-\omega _8^{-1}A^{[1]}(\omega _4^{-1}) \\ & a(\omega _8^{-6})=A^{[0]}(\omega _8^{-12})+\omega _8^{-6}A^{[1]}(\omega _8^{-12})=A^{[0]}(\omega _4^{-2})-\omega _8^{-2}A^{[1]}(\omega _4^{-2}) \\ & a(\omega _8^{-7})=A^{[0]}(\omega _8^{-14})+\omega _8^{-7}A^{[1]}(\omega _8^{-14})=A^{[0]}(\omega _4^{-3})-\omega _8^{-3}A^{[1]}(\omega _4^{-3}) \end{align*}$

$\begin{align*} A^{[0]}(x)&=f(\omega _8^0)+f(\omega _8^2)x+f(\omega _8^4)x^2+f(\omega _8^6)x^3 \\ &=f(\omega _8^0)+f(\omega _8^4)x^2+x(f(\omega _8^2)+f(\omega _8^6)x^2) \end{align*}$

令$B^{[0]}(x)=f(\omega _8^0)+f(\omega _8^4)x,B^{[1]}(x)=f(\omega _8^2)+f(\omega _8^6)x$

則$A^{[0]}(x)=B^{[0]}(x^2)+xB^{[1]}(x^2)$

$\begin{align*} &A^{[0]}(\omega _4^0) =B^{[0]}(\omega _4^0)+\omega _4^0B^{[1]}(\omega _4^0) =B^{[0]}(\omega _2^0)+\omega _4^0B^{[1]}(\omega _2^0) \\ &A^{[0]}(\omega _4^{-1})=B^{[0]}(\omega _4^{-2})+\omega _4^{-1}B^{[1]}(\omega _4^{-2})=B^{[0]}(\omega _2^{-1})+\omega _4^{-1}B^{[1]}(\omega _2^{-1}) \\ &A^{[0]}(\omega _4^{-2})=B^{[0]}(\omega _4^{-4})+\omega _4^{-2}B^{[1]}(\omega _4^{-4})=B^{[0]}(\omega _2^0)-\omega _4^0B^{[1]}(\omega _2^0) \\ &A^{[0]}(\omega _4^{-3})=B^{[0]}(\omega _4^{-6})+\omega _4^{-3}B^{[1]}(\omega _4^{-6})=B^{[0]}(\omega _2^{-1})-\omega _4^{-1}B^{[1]}(\omega _2^{-1}) \\ \end{align*}$

$\begin{align*} B^{[0]}(x)&=f(\omega _8^0)+f(\omega _8^4)x \\ &=f(\omega _8^0)+xf(\omega _8^4) \end{align*}$

$\begin{align*} &B^{[0]}(\omega _2^0)=a_0+\omega _2^0 a_4 \\ &B^{[0]}(\omega _2^{-1})=a_0+\omega _2^{-1} a_4=a_0-\omega _2^0 a_4 \\ \end{align*}$

相信給出一張圖片,你就能明白啦!!!

注意:處理的長度只能是2的次冪,所以對於多項式相乘,應該將長度n變成:大於等於n的最小的2的次冪,再乘以2。以保證不會溢出。
記得除以n。

代碼如下:

void FFT(complex<double> *a, int n, int inv) //inv=1 FFT inv=-1 IFFT
{
	if (n == 1)
		return;
	int mid = n / 2;
	for (int i = 0; i < mid; i++)
	{
		rev[i] = a[i*2];
		rev[i + mid] = a[i * 2 + 1];
	}
	for (int i = 0; i < n; i++)
	{
		a[i] = rev[i];
	}
	FFT(a, mid, inv);
	FFT(a + mid, mid, inv);
	for (int i = 0; i < mid; i++)
	{
		complex<double> w(cos(2 * pi * i / n), inv * sin(2 * pi * i / n));
		complex<double> l = a[i];
		complex<double> r = w * a[i+mid];
		a[i] = l+r;
		a[i + mid] = l-r;
	}
}

優化

上面的代碼層層遞歸,還是很耗時的,如果我們一開始就將各位數放到他們應該去的位置,就可以快很多了。

$$\begin{matrix} a_0 & a_1 & a_2 & a_3 & a_4 & a_5 & a_6 & a_7 \\ \downarrow & \downarrow & \downarrow & \downarrow & \downarrow & \downarrow & \downarrow &\downarrow \\ 000 & 001 & 010 & 011 & 100 & 101 & 110 & 111\\ \downarrow & \downarrow & \downarrow & \downarrow & \downarrow & \downarrow & \downarrow &\downarrow \\ 位反轉 & 位反轉 & 位反轉 & 位反轉 & 位反轉 & 位反轉 & 位反轉 & 位反轉 & \\ \downarrow & \downarrow & \downarrow & \downarrow & \downarrow & \downarrow & \downarrow &\downarrow \\ 000 & 100 & 010 & 110 & 001 & 101 & 011 & 111 \\ \downarrow & \downarrow & \downarrow & \downarrow & \downarrow & \downarrow & \downarrow &\downarrow \\ a_0 & a_4 & a_2 & a_6 & a_1 & a_5 & a_3 & a_7 \end{matrix}$$

代碼如下:

void FFT(complex<double>* a, int n, int inv)
{
	int bit = 0;
	while ((1 << bit) < n) bit++;
	for (int i = 0; i < n; i++)
	{
		rev[i] = a[(rev32bit(i) >> (32 - (bit)))];
	}
	for (int i = 0; i < n; i++)
	{
		a[i] = rev[i];
	}
	for (int mid = 1; mid < n; mid *= 2)
	{
		complex<double> w(cos(pi / mid), inv * sin(pi / mid));
		for (int i = 0; i < n; i += mid * 2)
		{
			complex<double> temp = 1;
			for (int j = 0; j < mid; j++, temp *= w)
			{
				//complex<double> w(cos(pi * j / mid), inv * sin(pi * j / mid));
				complex<double> l = a[i + j];
				complex<double> r = temp * a[i + j + mid];
				a[i + j] = l + r;
				a[i + j + mid] = l - r;
			}
		}
	}
}

32位反轉算法代碼如下:

unsigned int rev32bit(unsigned int x)
{
	 x = ((x & 0x55555555) << 1) | ((x & 0xaaaaaaaa) >> 1);
	 x = ((x & 0x33333333) << 2) | ((x & 0xcccccccc) >> 2);
	 x = ((x & 0x0f0f0f0f) << 4) | ((x & 0xf0f0f0f0) >> 4);
	 x = ((x & 0x00ff00ff) << 8) | ((x & 0xff00ff00) >> 8);
	 x = ((x & 0x0000ffff) << 16) | ((x & 0xffff0000) >> 16);
	 return x;
}
注意:上面的代碼不能直接用,例如4的位反轉為0x20000000。即00000000 00000000 00000000 00000100b反轉后為00100000 00000000 00000000 00000000b,我們需要右位移29(32-$\log_2^{長度}$)位,得到0x0001,即為1。

擴展

求解第一個大於等於n的2的次冪

代碼如下

int FGE2(int n)
{
	int temp = n - 1;
	temp |= temp >> 1;
	temp |= temp >> 2;
	temp |= temp >> 4;
	temp |= temp >> 8;
	temp |= temp >> 16;
	//temp |= temp >> 32; //如果類型是long long
	return  temp + 1;
}

大數FFT

我們以大數$abcdef$為例,$f(x)=f+ex+dx^2+cx^3+bx^4+ax^5+0x^6+0x^7$,則$f(10)=abcdef$

我們以$21\times 34$為例:

$$f(x)=1+2x+0x^2+0x^3$$

$$g(x)=4+3x+0x^2+0x^3$$

$$h(x)=f(x)g(x)=4+11x+6x^2+0x^3$$

$$(1+2x)(4+3x)=4+11x+6x^2$$

$$x=10,~21\times 34=4+110+600=714$$

實際中,將多項式系數進位就可以得到。例如將11進位,將1加到6,得到4,1,7。

例題

HDU 1402

#include <iostream>
#include <algorithm>
#include <complex>
#include <cstring>
using namespace std;

double pi = acos(-1);
complex<double> A[131072], B[131072];
int answer[131072];
char sa[50000], sb[50000];
unsigned int rev32bit(unsigned int x)
{
    x = ((x & 0x55555555) << 1) | ((x & 0xaaaaaaaa) >> 1);
    x = ((x & 0x33333333) << 2) | ((x & 0xcccccccc) >> 2);
    x = ((x & 0x0f0f0f0f) << 4) | ((x & 0xf0f0f0f0) >> 4);
    x = ((x & 0x00ff00ff) << 8) | ((x & 0xff00ff00) >> 8);
    x = ((x & 0x0000ffff) << 16) | ((x & 0xffff0000) >> 16);
    return x;
}
void FFT(complex<double>* a, int n, int inv)
{
    int bit = 0;
    while ((1 << bit) < n) bit++;
    for (int i = 0; i < n; i++)
    {
        int temp = rev32bit(i) >> (32 - (bit));
        if (i < temp)
            swap(a[i], a[temp]);
    }
    for (int mid = 1; mid < n; mid *= 2)
    {
        complex<double> w(cos(pi / mid), inv * sin(pi / mid));
        for (int i = 0; i < n; i += mid * 2)
        {
            complex<double> temp = 1;
            for (int j = 0; j < mid; j++, temp *= w)
            {
                //complex<double> w(cos(pi * j / mid), inv * sin(pi * j / mid));
                complex<double> l = a[i + j];
                complex<double> r = temp * a[i + j + mid];
                a[i + j] = l + r;
                a[i + j + mid] = l - r;
            }
        }
    }
}
int FGE2(int n)
{
    int temp = n - 1;
    temp |= temp >> 1;
    temp |= temp >> 2;
    temp |= temp >> 4;
    temp |= temp >> 8;
    return  temp + 1;
}
int main(int argc, char* argv[])
{
    while (~scanf("%s%s", sa, sb))
    {
        int len1 = strlen(sa);
        int len2 = strlen(sb);
        int len = FGE2(max(len1, len2)) * 2;

        for (int i = 0; i < len1; i++)
            A[i] = sa[len1 - i - 1] - '0';
        for (int i = len1; i < len; i++)
            A[i] = 0;
        for (int i = 0; i < len2; i++)
            B[i] = sb[len2 - i - 1] - '0';
        for (int i = len2; i < len; i++)
            B[i] = 0;

        FFT(A, len, 1);
        FFT(B, len, 1);
        for (int i = 0; i < len; i++)
        {
            A[i] = A[i] * B[i];
        }
        FFT(A, len, -1);
        for (int i = 0; i < len; i++)
        {
            answer[i] = (int)(A[i].real() / len + 0.5);
        }
        for (int i = 0; i < len - 1; i++)
        {
            answer[i + 1] += answer[i] / 10;
            answer[i] %= 10;
        }
        int index;
        for (index = len - 1; index > 0; index--)
        {
            if (answer[index] != 0)
                break;
        }
        for (int i = index; i >= 0; i--)
        {
            printf("%d", answer[i]);
        }
        printf("\n");
    }
    return 0;
}

洛谷 P1919

只需要將數組大小改成2097152和1000000即可。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM