生活随笔
收集整理的這篇文章主要介紹了
51nod 1172 Partial Sums V2 卡精度的任意模数FFT
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
卡精度的任意模數fft模板題……
這道題隨便寫個表就能看出規(guī)律來(或者說考慮一下實際意義),反正拿到這題之后,很快就會發(fā)現(xiàn)他是任意模數fft模板題.
然后我就去網上抄了一下板子……
我打的是最土的任意模數fft,就是fft7次的那種……(好像有很多方法的樣子……)
這種任意模數fft方法見http://blog.csdn.net/l_0_forever_lf/article/details/52886397
這道題的具體做法見http://blog.csdn.net/qq_33229466/article/details/78837522
這種方法的思想就是:
I.既然出題人給出了任意模數的多項式乘法,那么常規(guī)ntt肯定是不行
II.既然他取模,那數會很大,會炸精,常規(guī)的fft也不行
III.既然直接乘會炸精,那我們就把數變小,多跑幾次也沒關系
(IV.感覺加了一維卷積,有種這種方法很妙,可以繼續(xù)擴展的感覺,但是很模糊,也說不具體)
本著這種思路,我們逆變換的時候,不能在點值表達式直接操作,最后一遍回去,因為這樣效果和沒有在一開始把數縮小一樣,會炸精.
最后說一下這道題的坑點:如果你不預處理復數,你會炸精.
好像有的人沒有預處理,但是用了long double,就沒有被卡……
似乎cmath庫里有標準庫也有類庫,而且有的函數兩者并不都具有,但是最坑爹的一點是對于sin,cos等函數,cmath標準庫的精度大于cmath類庫……(這只是我經過親身試驗做出的推測)
反正預處理就沒有這些破事……
#include <cmath>
#include <cstdio>
#include <cstring>
#include <complex>
#include <algorithm>
typedef long long LL;
typedef double db;
typedef std::complex<db>
cd;
const int N=
200010;
const db Pai=acos((db)-
1);
const int P=
1000000007;
cd a1[N],b1[N],a2[N],b2[N],c1[N],c2[N],c3[N],w1[N],w2[N];
int rev[N],len;
int ai[N],bi[N],ans[N],ni[N];
inline void fft(cd *C,
int opt,cd *
wn){register int i,j,k;cd temp;for(i=
1;i<len;++i)
if(rev[i]>
i)std::swap(C[i],C[rev[i]]);for(k=
2;k<=len;k<<=
1){for(i=
0;i<len;i+=
k){for(j=
0;j<(k>>
1);++
j){temp=C[i+j+(k>>
1)]*wn[len/k*
j];C[i+j+(k>>
1)]=C[i+j]-
temp;C[i+j]+=
temp;}}}if(opt==-
1){db inv=
1./
len;for(i=
0;i<len;++i)C[i]*=
inv;}
}
inline void Mul(
int *a,
int *b,
int *c,
int n){len=
1;while(len<n)len<<=
1;int i,sqr=
sqrt(P);cd temp;for(i=
1;i<len;++i)rev[i]=(rev[i>>
1]>>
1)|((i&
1)?(len>>
1):
0);for(i=
0;i<len;++
i){w1[i]=cd(std::cos(
2.*Pai/len*i),std::sin(
2.*Pai/len*
i));w2[i]=cd(std::cos(-
2.*Pai/len*i),std::sin(-
2.*Pai/len*
i));}for(i=
0;i<len;++
i){a1[i]=ai[i]/sqr,b1[i]=ai[i]%
sqr;a2[i]=bi[i]/sqr,b2[i]=bi[i]%
sqr;}fft(a1,1,w1),fft(b1,
1,w1),fft(a2,
1,w1),fft(b2,
1,w1);for(i=
0;i<len;++
i){c1[i]=a1[i]*
a2[i];c2[i]=a1[i]*b2[i]+a2[i]*
b1[i];c3[i]=b1[i]*
b2[i];}fft(c1,-
1,w2),fft(c2,-
1,w2),fft(c3,-
1,w2);for(i=
0;i<len;++
i)c[i]=((LL)(round(c1[i].real()))%P*sqr%P*sqr%P+(LL)(round(c2[i].real()))%P*sqr%P+(LL)(round(c3[i].real()))%P)%
P;
}
int main(){int n,k,i;scanf("%d%d",&n,&
k);for(i=
0;i<n;++i)scanf(
"%d",&
ai[i]);bi[0]=
1;for(i=
1;i<n;++
i)bi[i]=(LL)bi[i-
1]*(k+i-
1)%P*(i==
1?ni[i]=
1:ni[i]=(-(LL)(P/i)*ni[P%i]%P+P)%P)%
P;Mul(ai,bi,ans,n<<
1);for(i=
0;i<n;++i)printf(
"%d\n",ans[i]);return 0;
} ?
轉載于:https://www.cnblogs.com/TSHugh/p/8490076.html
總結
以上是生活随笔為你收集整理的51nod 1172 Partial Sums V2 卡精度的任意模数FFT的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。