日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

HDU1402(FFT入门)

發布時間:2023/11/27 生活经验 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 HDU1402(FFT入门) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目鏈接:http://acm.hdu.edu.cn/status.php?user=Reykjavik11207&pid=1402&status=5

本題數據范圍為5e4,常規方法O(n2)肯定是不行的。

FFT是離散傅里葉變換DFT的快速形式

對多項式f(x) = a0 + a1x + a2x2 + ··· +an-1xn-1,有兩種表示法:

系數表達式 : (a0 , a1 , ··· , an-1)

由于n-1次多項式需要n個點來確定

所以可以用點值表達式 : ( (x0,f(x0)) , (x1,f(x1)) , ··· , (xn-1,f(xn-1)) ) 來表示

要獲得點值表達式,首先選取n個x值獲得對應f(x)的值

將f(x)分為奇偶兩個部分f(x) = a0 + a2x2 + ··· + an-2xn-2 + a1x + a3x3 + ··· + an-1xn-1

f1(x) = a0 + a2x + ··· + an-2 x(n-2)/2

?? f2(x) = a1 + a3x + ··· + an-1 x(n-1)/2

則有f(x) = f1(x2) + xf2(x2)?

f1(x)與f2(x)再分別分解,直至到常數ai為止

到了這里,復雜度并沒有降低,反而由于x的整次冪未知還升高了,可以發現x = 1可以使式子更簡單,因為1的多少次冪都是1,然后就是-1,但只有2個數遠遠不夠,所以引入了復數。

?

是復平面單位圓上逆時針按k從小到大均勻分布的復根,間隔角度為2π/n,所以有:

= cos(2kπ/n) + i * sin(2kπ/n) ,計算復根的k次冪顯然較實數更為方便,(但STL中三角函數也不是O(1),是多少我也不太懂,總之我把wnk函數放三重循環里就超時了)。

容易看出它的周期為n,即滿足

同時還有以下性質:? =? cos(2kπ/n + π) + i * sin(2kπ/n + π) =

=? cos(2*2k*π/n) + i * sin(2*2k*π/n) = cos(2kπ/(n/2)) + i * sin(2kπ/(n/2)) =

故f(wnk+n/2) = f1(wn/2k) - wnk?f2(wn/2k)

以n = 4為例:

顯然n必須為2的整數次冪

原來第i個元素的位置經過變換后的位置為i的二進制按長度翻轉,

如上圖中(0)10 = (00)2?? 翻轉 ->?? (00)2 = (0)10

    (1)10 = (01)2?? 翻轉 ->?? (10)2 = (2)10

    (2)10 = (10)2 ? 翻轉->??? (01)2 = (1)10

    (3)10 = (11)2?? 翻轉->??? (11)2 = (3)10

然后自底向上代入函數中,得到n個f(x)值

另一個數同理得到n個g(x)值

F(x) = f(x)*g(x),則F(xi) = f(xi)*g(xi)

接下來就要用傅里葉逆變換IDFT求出F(x)的系數表達式

變換矩陣

的逆矩陣為

進而得到F(x)的系數表達式,即為結果

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1 << 17;
const double pi = acos(-1.0);
const double eps = 1e-4;//這個...精度問題,本來用的1e-8就WA了
int n,len;
int rev(int x)//二進制翻轉
{int res = 0;for(int i = 0; i < len; i++)res += ((x >> i) & 1) << (len - 1 - i);return res;
}
struct Complex
{double real,image;Complex(double r = 0,double i = 0){real = r;image = i;}Complex operator + (const Complex &t){return Complex(real + t.real, image + t.image);}Complex operator - (const Complex &t){return Complex(real - t.real, image - t.image);}Complex operator * (const Complex &t){return Complex(real * t.real - image * t.image, real * t.image + t.real * image);}
};
Complex wnk(double n,double k)
{return Complex(cos(2*pi*k/n), sin(2*pi*k/n));
}
void fft(Complex y[], int dft)
{Complex t1,t2;for(int i = 1; i < n; i <<= 1){Complex W(1,0), w = wnk(2*i,dft);for(int k = 0; k < i; k++){for(int j = k; j < n; j += i<<1){t1 = y[j] + W * y[j+i];t2 = y[j] - W * y[j+i];y[j] = t1;y[j+i] = t2;}W = W * w;}}if(dft == -1){for(int i = 0; i < n; i++)y[i].real /= n;}
}
Complex a1[N],a2[N],a[N];
int ans[N];
char stra[N>>1],strb[N>>1];
int main()
{while(~scanf("%s %s",stra,strb)){int lena = strlen(stra);int lenb = strlen(strb);len = log10(lena+lenb)/log10(2) + 1 + eps;n = 1 << len;for(int i = 0; i < lena; i++)a1[rev(i)] = Complex((double)(stra[lena-i-1] - '0'), 0);for(int i = lena; i < n; i++)a1[rev(i)] = Complex(0,0);for(int i = 0; i < lenb; i++)a2[rev(i)] = Complex((double)(strb[lenb-i-1] - '0'), 0);for(int i = lenb; i < n; i++)a2[rev(i)] = Complex(0,0);fft(a1,1);fft(a2,1);for(int i = 0; i < n; i++)a[rev(i)] = a1[i] * a2[i];fft(a,-1);int t = 0;for(int i = 0; i < n; i++){ans[n - 1 - i] = ((int)(a[i].real + eps) + t) % 10;t = ((int)(a[i].real + eps) + t) / 10;}bool flag = 0;for(int i = 0; i < n - 1; i++){if(ans[i])flag = 1;if(!flag)continue;printf("%d",ans[i]);}printf("%d\n",ans[n-1]);}return 0;
}

?

???(W0n)0(W1n)0?(Wn?1n)0(W0n)1(W1n)1?(Wn?1n)1????(W0n)n?1(W1n)n?1?(Wn?1n)n?1?????????????a0a1?an?1??????

???(W0n)0(W1n)0?(Wn?1n)0(W0n)1(W1n)1?(Wn?1n)1????(W0n)n?1(W1n)n?1?(Wn?1n)n?1?????????????a0a1?an?1??????

轉載于:https://www.cnblogs.com/westwind1005/p/8886973.html

總結

以上是生活随笔為你收集整理的HDU1402(FFT入门)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。