51nod 1172 Partial Sums V2 卡精度的任意模数FFT
2018-03-01 18:51
429 查看
卡精度的任意模数fft模板题……
这道题随便写个表就能看出规律来(或者说考虑一下实际意义),反正拿到这题之后,很快就会发现他是任意模数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.既然出题人给出了任意模数的多项式乘法,那么常规ntt肯定是不行
II.既然他取模,那数会很大,会炸精,常规的fft也不行
III.既然直接乘会炸精,那我们就把数变小,多跑几次也没关系
(IV.感觉加了一维卷积,有种这种方法很妙,可以继续扩展的感觉,但是很模糊,也说不具体)
本着这种思路,我们逆变换的时候,不能在点值表达式直接操作,最后一遍回去,因为这样效果和没有在一开始把数缩小一样,会炸精.
最后说一下这道题的坑点:如果你不预处理复数,你会炸精.
好像有的人没有预处理,但是用了long double,就没有被卡……
似乎cmath库里有标准库也有类库,而且有的函数两者并不都具有,但是最坑爹的一点是对于sin,cos等函数,cmath标准库的精度大于cmath类库……(这只是我经过亲身试验做出的推测)
反正预处理就没有这些破事……
这道题随便写个表就能看出规律来(或者说考虑一下实际意义),反正拿到这题之后,很快就会发现他是任意模数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.既然出题人给出了任意模数的多项式乘法,那么常规ntt肯定是不行
II.既然他取模,那数会很大,会炸精,常规的fft也不行
III.既然直接乘会炸精,那我们就把数变小,多跑几次也没关系
(IV.感觉加了一维卷积,有种这种方法很妙,可以继续扩展的感觉,但是很模糊,也说不具体)
本着这种思路,我们逆变换的时候,不能在点值表达式直接操作,最后一遍回去,因为这样效果和没有在一开始把数缩小一样,会炸精.
最后说一下这道题的坑点:如果你不预处理复数,你会炸精.
好像有的人没有预处理,但是用了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 ,b1 ,a2 ,b2 ,c1 ,c2 ,c3 ,w1 ,w2 ; int rev ,len; int ai ,bi ,ans ,ni ; 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; }
相关文章推荐
- 51nod 1172 Partial Sums V2 任意模数FFT
- 51NOD 1258 序列求和 V4 [任意模数fft 多项式求逆元 伯努利数]
- 【51nod 1028】 大数乘法 V2 【FFT/NTT】
- 51NOD 1185 威佐夫游戏 V2(博弈论 + 减少精度)
- [51nod 1258] [伯努利数] [多项式求逆] [任意模数NTT] 序列求和 V4
- 任意模数FFT 板子
- [组合数] 51Nod 1161 Partial Sums & Codeforces 223C #138 (Div. 1) Partial Sums
- 51nod 1161 Partial Sums
- [置顶] 多项式求逆,除法,开方,任意模数FFT
- 51nod 1185 威佐夫游戏 V2 (用乘法模拟解决大数精度问题)
- [FFT] 51Nod 1028 大数乘法 V2
- 【51nod】1123 X^A Mod B (任意模数的K次剩余)
- 51nod 1028 大数乘法 V2 【FFT模板题】
- 【51nod】1089 最长回文子串 V2(Manacher算法)
- BZOJ1042 HAOI2008硬币购物(任意模数NTT+多项式求逆+生成函数/容斥原理+动态规划)
- 51nod 1119 机器人走方格V2 lucas定理
- hihocoder 1388 2016北京网络赛1006 Periodic Signal(卡精度的FFT)
- HDU-4193 Non-negative Partial Sums
- 51Nod 1130 N的阶乘的长度 V2(斯特林近似)
- 51Nod-1185-威佐夫游戏 V2