求Q(x)模X^n + 1的餘數多項式的FFT算法

Q\left ( x \right )X^{n}+1的餘數多項式,最高次數不超過n,令其餘數多項式的形式爲f\left ( x \right )=a_{0}+a_{1}x+a_{2}x^{2}+......+a_{n-1}x^{n-1}

 

1、因爲X^{n}+1有n個解,對應餘數多項式有n個,分別是\left \{ f\left ( x_{j} \right ) \right \}其中,0<=j<=n-1,而x_{_{j}}則是X^{n}+1的n個解,而x_{_{j}}是容易求的,

x_{j} = e^{i\left ( \pi /n\right )\left ( 2j+1 \right )},但是如果每個都往\left \{ f\left ( x_{j} \right ) \right \}裏面帶入的話,會花費大量的計算量。

 

這裏提一種基於FFT的簡單運算,這裏要求n=2^{k}。(這裏對爲什麼是基於FFT的我也不是很明白,有一說是

\left ( a_{0} ,a_{1},...a_{n-1}\right )\rightarrow \left ( f\left ( x_{0} \right ) ,f\left ( x_{1} \right ),....,f\left ( x_{n-1} \right )\right )的離散傅里葉變換DFS,用快速傅里葉變換FFT計算得來的,DFS的公式這兒就不列出了)

 

2、計算算法,因爲n=2^{k},把f\left ( x \right )=a_{0}+a_{1}x+a_{2}x^{2}+......+a_{n-1}x^{n-1}按奇偶項分開,每次分開一半,直到最後只剩兩項的時候進行計算,然後一直遞歸向上,這樣就把大量的乘冪運算轉化爲了加法運算,下面給出C語言的代碼

 


//

#include "stdafx.h"

#define _CRT_SECURE_NO_WARNINGS
#include "stdlib.h"
#include "math.h"
#include "stdio.h"


#define K 3

#define Pi  3.1415927   //定義圓周率Pi
#define LEN sizeof(struct Compx)  //定義複數結構體大小

//-----定義複數結構體-----------------------
struct Compx
{
	double real;
	double imag;
}Compx;

//-----複數乘法運算函數---------------------
struct Compx mult(struct Compx b1, struct Compx b2)
{
	struct Compx b3;
	b3.real = b1.real*b2.real - b1.imag*b2.imag;
	b3.imag = b1.real*b2.imag + b1.imag*b2.real;
	return(b3);
}

//-----複數加法運算函數---------------------
struct Compx add(struct Compx a, struct Compx b)
{
	struct Compx c;
	c.real = a.real + b.real;
	c.imag = a.imag + b.imag;
	return(c);
}

struct Compx FFT(struct Compx *t , int n , struct Compx root , struct Compx result ) ;

int main(  ) 
{
	int N,i;
	N =8;

    int x[8];
    for( i = 0 ; i < N; i++ )
	{
    	scanf("%d",&x[i]);
	}
	
    struct  Compx * Source = (struct Compx *)malloc(N*LEN);			//爲結構體分配存儲空間
    struct  Compx * Result = (struct Compx *)malloc(N*LEN);
    struct  Compx * Root = (struct Compx *)malloc(N*LEN);

    
    //初始化======================================= 
    printf("\nSource初始化:\n");
	for (i = 0; i<N; i++)
	{
		Source[i].real = x[i];
		Source[i].imag = 0;
		printf("%.4f ", Source[i].real);
		printf("+%.4fj  ", Source[i].imag);
		printf("\n");
	}
	printf("\nResult初始化:\n");
	for (i = 0; i<N; i++)
	{
		Result[i].real = 0;
		Result[i].imag = 0;
		printf("%.4f ", Result[i].real);
		printf("+%.4fj  ", Result[i].imag);
		printf("\n");
	}
	printf("\nRoot初始化:\n");
	for (i = 0; i<N; i++)
	{
		Root[i].real = cos( Pi * ( 2 * i + 1) / (2 * N));
		Root[i].imag = sin( Pi * ( 2 * i + 1) / (2 * N));
		printf("%.4f ", Root[i].real);
		printf("+%.4fj  ", Root[i].imag);
		printf("\n");
	}
	

    for( i = 0 ; i < N ; i++) 
    {
    	Result[i] = FFT(Source , N , Root[i] , Result[i]);
	}
	
    //結果表示
	printf("\nResult計算結果:\n");
	for (i = 0; i<N; i++)
	{
		printf("%.4f ", Result[i].real);
		printf("+%.4fj  ", Result[i].imag);
		printf("\n");
	}
    
	return 0;
}

struct Compx FFT(struct Compx *t , int n , struct Compx root , struct Compx result ) 
{
	int i,j;
	struct  Compx * even = (struct Compx *)malloc((n / 2) * LEN);	
	struct  Compx * odd = (struct Compx *)malloc((n / 2) * LEN);
	
	//劃分奇偶項 
	for (i = 0 , j = 0 ; i < n; i += 2 , j++ )
	{
		even[j].real = t[i].real;
		even[j].imag = t[i].imag;
	}
	for (i = 1 , j = 0 ; i < n; i += 2 , j++)
	{
		odd[j].real = t[i].real;
		odd[j].imag = t[i].imag;
	}
	
	if(n == 2)
	{
		struct Compx s = add( even[0] , mult( root , odd[0]) );
		return add(result , s);
	}
	else
	{
		return add( FFT(even , n / 2 , mult(root , root) , result ) , mult( root , FFT(odd , n / 2 , mult(root , root) , result ) ) );
	}
}

歡迎指正!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章