模意義下的FFT算法

//寫在前面 單就FFT算法來說的話,下面只給出個人認為比較重要的推導,詳細的介紹可參考  FFT算法學習筆記

令v[n]是長度為2N的實序列,V[k]表示該實序列的2N點DFT。定義兩個長度為N的實序列g[n]和h[n]為

?g[n]=v[2n],  h[n]=v[2n+1],  0<=n<N?

則可進行如下推導

這里所用的FFT算法能夠實現O(nlogn)復雜度的離散傅里葉變換和上面最后所得的關系密切相關。

?

下面進入正題——模意義下的FFT

還是需要先了解一下關于 復序列的DFT的對稱性質及一些補充定義?

由此,可以試想,假設說要模的素數p為1e8級別大小,那么我們可以把原始的實序列x[n]“拆”一下。

下面假設我們要求的是x[n]卷積y[n]的結果t[n]。

假設q是sqrt(p)級別的一個數,我們可以把x[n]/q存到復序列x1[n]的實部,x[n]%q存到復序列x1[n]的虛部。這時,對x1[n]、y1[n]求DFT,再由X1[k]*Y1[k]得到T1[k],整個運算過程中能夠產生的最大浮點數為N*q^2級別,一般來說還是在可以接受的范圍內的。

接下來考慮從卷積結果{T1[k]}中恢復出原始的t[n]的過程。

看一下T1[k]的組成

到這里差不多就可以結束了。發現上面最后一行等號右邊有四個“乘積”,我們可以把上面四個乘積分別單獨拿出來,求IDFT就可以恢復出x/y_re/im卷積的結果,之后針對不同的乘積,考慮需要在模p意義下乘上q^2、q^1或q^0,來進行恢復就可以了。

奉上模板

namespace FFT_MO    //前面需要有 mod(1e8~1e9級別),upmo(a,b) 的定義 
{const int FFT_MAXN=1<<18;const db pi=3.14159265358979323846264338327950288L;struct cp{db a,b;cp(double a_=0,double b_=0){a=a_,b=b_;}cp operator +(const cp&rhs)const{return cp(a+rhs.a,b+rhs.b);}cp operator -(const cp&rhs)const{return cp(a-rhs.a,b-rhs.b);}cp operator *(const cp&rhs)const{return cp(a*rhs.a-b*rhs.b,a*rhs.b+b*rhs.a);}cp operator !()const{return cp(a,-b);}}nw[FFT_MAXN+1],f[FFT_MAXN],g[FFT_MAXN],t[FFT_MAXN];    //a<->f,b<->g,t<~>c int bitrev[FFT_MAXN]; void fft_init()    //初始化 nw[],bitrev[] 
    {int L=0;while((1<<L)!=FFT_MAXN) L++;for(int i=1;i<FFT_MAXN;i++)  bitrev[i]=bitrev[i>>1]>>1|((i&1)<<(L-1));for(int i=0;i<=FFT_MAXN;i++) nw[i]=cp((db)cosl(2*pi/FFT_MAXN*i),(db)sinl(2*pi/FFT_MAXN*i));}// n已保證是2的整數次冪 // flag=1:DFT |  flag=-1: IDFTvoid dft(cp *a,int n,int flag=1)    {int d=0;while((1<<d)*n!=FFT_MAXN) d++;for(int i=0;i<n;i++) if(i<(bitrev[i]>>d))swap(a[i],a[bitrev[i]>>d]);for(int l=2;l<=n;l<<=1){int del=FFT_MAXN/l*flag;    // 決定 wn是在復平面是順時針還是逆時針變化,以及變化間距 for(int i=0;i<n;i+=l){cp *le=a+i,*ri=a+i+(l>>1);cp *w=flag==1? nw:nw+FFT_MAXN;    // 確定wn的起點 for(int k=0;k<(l>>1);k++){cp ne=*ri * *w;*ri=*le-ne,*le=*le+ne;le++,ri++,w+=del;}}}if(flag!=1) for(int i=0;i<n;i++) a[i].a/=n,a[i].b/=n;}// convo(a,n,b,m,c) a[0..n]*b[0..m] -> c[0..n+m]void convo(LL *a,int n,LL *b,int m,LL *c){for(int i=0;i<=n+m;i++) c[i]=0;int N=2;while(N<=n+m) N<<=1;    // N是c擴展后的長度 for(int i=0;i<N;i++)    //擴展 a[],b[] ,存入f[],g[],注意取模 
        {LL aa=i<=n?a[i]:0,bb=i<=m? b[i]:0;     aa%=mod,bb%=mod;f[i]=cp(db(aa>>15),db(aa&32767));g[i]=cp(db(bb>>15),db(bb&32767));}dft(f,N),dft(g,N);for(int i=0;i<N;i++)    // 恢復虛部兩個“乘積”(乘積具體意義見上文)
        {int j=i? N-i:0;t[i]=((f[i]+!f[j])*(!g[j]-g[i])+(!f[j]-f[i])*(g[i]+!g[j]))*cp(0,0.25);}dft(t,N,-1);for(int i=0;i<=n+m;i++)    upmo(c[i],(LL(t[i].a+0.5))%mod<<15);for(int i=0;i<N;i++)    // 恢復實部兩個“乘積”
        {int j=i? N-i:0;t[i]=(!f[j]-f[i])*(!g[j]-g[i])*cp(-0.25,0)+cp(0,0.25)*(f[i]+!f[j])*(g[i]+!g[j]);}dft(t,N,-1);for(int i=0;i<=n+m;i++)    upmo(c[i],LL(t[i].a+0.5)+(LL(t[i].b+0.5)%mod<<30));}
}
模板

舉個栗子~  ?hdu 6088 Rikka with Rock-paper-scissors (2017 多校第五場 1004) 【組合數學 + 數論 + 模意義下的FFT】

?

//本博客主要參考資料:數字信號處理——基于計算機的方法(第四版)  [美] Sanjit K. Mitra 著  余翔宇 譯

轉載請注明出處?http://www.cnblogs.com/Just--Do--It/p/7892254.html

謝謝閱讀

?

轉載于:https://www.cnblogs.com/Just--Do--It/p/7892254.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/251480.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/251480.shtml
英文地址,請注明出處:http://en.pswp.cn/news/251480.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

bootstrap --- 標簽頁切換

很多時候,我們希望寫一個簡單的標簽頁.以下使用bootstrap來實現… 首先導入bootstrap的依賴:jquery的依賴、bootstrap的依賴 注意: jquery的依賴要在bootstrap依賴的前面導入,原因是:bootstrap的某些功能是在jquery的基礎上實現的 在 https://www.bootcdn.cn/jquery/ 導入jqu…

bootstrap --- 鼠標停留提示事件

使用bootstrap可以很簡單的實現鼠標停留,提示的效果 <a href"#" data-toggle"tooltip" data-placement"right" title"Tooltip on right" class"btn btn-primary">工具提示</a> // data-toggle"tooltip&…

day 3 list列表生成式

1.定義一個list列表&#xff0c;里面元素是0-33 a []i 0 while i<33:a.append(i)i1print(a) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32] 2.range &#xff08;切片&#xff09; 1&…

2020校招前端知識點整理

自用的前端知識點整理筆記&#xff08;長期更新&#xff09; 開啟面試造火箭模式&#x1f4d4;&#x1f448;點擊獲得更好的閱讀體驗 有錯誤的地方請指出&#xff0c;感激不盡 HTML 你是如何理解HTML語義化的&#xff1f;? 總結&#xff1a;用恰當的標簽來標記內容。 比如…

day18 面向對象

---恢復內容開始--- 1.1類的相關知識 聲明 def functionName(args):"函數文檔字符串""""函數體""" class 類名:"""類的文檔字符串""""""類體""" #我們創建一個類 class…

Android studio導入support-v4.jar

support-v4.jar是support library。路徑為<sdk>/extras/android/support/v4/android-support-v4.jar.轉載于:https://www.cnblogs.com/Magina-learning/p/7899788.html

html5 --- 特性檢測

使用Moderniz庫可以對H5的特性進行檢測,下載網址: https://modernizr.com // 在HTML 中的head標簽中導入 <script src"/modernizr.min.js"></script>// ps:注意src的路徑畫布(canvas)特性檢測: if (Modernizr.canvas){// 開始畫... } else {// 瀏覽器不…

編程學習筆記(第三篇)面向對象技術高級課程:緒論-軟件開發方法的演化與最新趨勢(3)軟件開發的現狀、UML擴展...

一、軟件開發的現狀 軟件領域正在發生一個巨變&#xff0c;特別是近幾年來&#xff0c;軟件領域正在發生翻天覆地的變化。 這一變化主要以這個云 端大數據&#xff0c; 這些是隨著目前最先進的一些技術的產生而產生的。 隨著這些新的技術以及軟件開發方法的不斷的提升&#xf…

百度地圖得到兩地點(通過經緯度)的距離、 通過經緯度獲取詳細地址

1 /**2 * 計算兩點間的距離3 * pt1 {lng:"12.34",lat:"3423"}第一個點的經緯度4 * pt2 {lng:"12.34",lat:"3423"}第二個點的經緯度5 * */6 getDistance:function(pt1,pt2){7 var map new BMap.Map(&…

html5 --- canvas繪制網格并畫x、y軸

效果如下: // 代碼如下: <body><canvas width"500" height"375" id"c"></canvas><script>(function draw_a() {var a_canvas document.getElementById("c");var context a_canvas.getContext("2d&qu…

系統調用軟中斷處理程序system_call分析

最近學習了系統調用的整個流程&#xff0c;這里總結并記錄。同時作為學習孟寧老師的linux內核課程的作業。 唐建&#xff0c;《Linux內核分析》MOOC課程http://mooc.study.163.com/course/USTC-1000029000 1、概述 系統調用整個過程為&#xff1a;API——封裝例程——system_c…

Poj3261 Milk Patterns

題目傳送門 題意&#xff1a;對一個字符串求一個最長的子串使得它至少出現k次 額&#xff0c;因為這個題目呢&#xff0c;他的字符集非常大(100W) 所以直接用SAM是不行了&#xff0c;我們考慮用離散化SA&#xff0c;讓后就可以分塊rmq了 當然這樣很麻煩&#xff0c;我們還是用S…

html5 --- 使用canvas畫一個漸變矩形

我們希望得到如下效果: 首先準備畫布 // HTML <canvas width"500" height"375" id "a"> </canvas>// JS // 獲取畫布的DOM元素 var a_canvas document.getElementById("1"); // 獲取畫布的上下文元素(之后,就可以使用…

PHP優化與提升

一。十個不錯的建議1.使用 ip2long() 和 long2ip() 函數來把 IP 地址轉化成整型存儲到數據庫里。這種方法把存儲空間降到了接近四分之一&#xff08;char(15) 的 15 個字節對整形的 4 個字節&#xff09;&#xff0c;計算一個特定的地址是不是在一個區段內頁更簡單了&#xff0…

Servlet詳解之兩個init方法的作用

在Servlet中 javax.servlet.GenericServlet類 繼承自java.lang.Object 實現了Serializable,&#xff0c;servlet &#xff0c;ServletConfig 三個接口 被繼承對象javax.servlet.http.HttpServlet &#xff08;這是我們常用的一個類&#xff09; 但仔細看GenericServlet的API&am…

vue --- 使用vue在html上顯示當前時間

希望如下效果(時間按秒鐘更新) 導入Vue依賴的CDN <script src"https://unpkg.com/vue/dist/vue.min.js"> </script>創建視圖 <div id"app">{{date}}</div>Model <script>var app new Vue({el: "app",data: …

namespace 或The content of element type mapper must match EMPTY

必須為元素類型 "mapper" 聲明屬性 "namespace" 或The content of element type "mapper" must match "EMPTY" <?xml version"1.0" encoding"UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org/…

EAS WebService部署

1、創建 facade ,設置好接口及參數、返回信息; 2、代碼&#xff1a;元數據打包部署到服務器; 3、然后修改配置文件&#xff1a; 將本地開發環境生成的.wsdd文件拷貝到eas\server\deploy\eas.ear的web.war下的WEB-INF目錄下&#xff0c;再將.wsdd文件中的<service></se…

vue --- 購物車頁面

下面我看開始自己寫一個購物車的頁面. 我們希望得到如下的效果: 說明: 購買數量最小為0購買數量變化時,對應的總價隨之變化點擊移除操作對應的商品會移除掉,總價隨之改變每個商品作為一個list表的一個對象每個對象,包含id、name、price、count等屬性 index.html (整體代碼最…

Javascript阻止表單提交

Javascript阻止表單提交 Html 1.<form name"loginForm" action"login.aspx" method"post"> 2. <button type"submit" value"Submit" id"submit">Submit</button> 3.</form> Js …