快速傅里叶变换(FFT)和数论变换(NTT)模板
2016-09-04 15:39
302 查看
#include<bits/stdc++.h> #define ll long long #define dob complex<double> const int N=120010; const double pi=acos(-1.0); using namespace std; inline int rd() { int x=0,res=1;char ch=getchar(); while(ch>'9'||ch<'0'){if(ch=='-')res*=-1;ch=getchar();} while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar(); return x*res; } int n,m,L,R ; dob a ,b ; void FFT(dob *A,int n,int f) { for(int i=0;i<n;i++)if(i<R[i])swap(A[i],A[R[i]]); for(int i=1;i<n;i<<=1) { dob wn(cos(pi/i),sin(f*pi/i)),x,y; for(int j=0;j<n;j+=(i<<1)) { dob w(1,0); for(int k=0;k<i;k++,w*=wn) { x=A[j+k];y=w*A[j+i+k]; A[j+k]=x+y; A[j+i+k]=x-y; } } } } int main() { while(~scanf("%d%d",&n,&m)) { for(int i=0;i<n;i++)a[i]=rd();//复数一定要用读入挂读入 for(int i=0;i<m;i++)b[i]=rd(); int len=1,s=n+m; L=0; for(;len<s;len<<=1)++L; for(int i=n;i<len;i++)a[i]=0; for(int i=n;i<len;i++)b[i]=0; for(int i=0;i<len;i++)R[i]=(R[i>>1]>>1)|((i&1)<<(L-1));//一定要预处理 FFT(a,len,1);FFT(b,len,1); for(int i=0;i<len;i++)a[i]*=b[i]; FFT(a,len,-1); for(int i=0;i<=s;i++)printf("%d ",int(a[i].real()/len+0.5));puts("");//idft以后要除len } }
#include<bits/stdc++.h>
#define ll long long
const int N=262144;
const ll MOD=50000000001507329LL;//998244353 1004535809
using namespace std;
int n,m;
ll a
,b
,x
,y
;
ll wn[25];
ll Mul(ll x,ll y)//乘法超ll用快速乘,主函数也需要用
{
ll ans=(x*y-(ll)((long double)x/MOD*y+1e-8)*MOD);
return ans<0?ans+MOD:ans;
}
ll Qpow(ll a,ll b,ll M)
{
ll ans=1;a%=M;
while(b)
{
if(b&1) ans=Mul(ans,a);
a=Mul(a,a);
b>>=1;
}
return ans;
}
void Getwn()//主函数预处理getwn()
{
for(int i=0;i<25;i++)
{
wn[i]=Qpow(3,(MOD-1)/(1<<i),MOD);
}
}
void NTT(ll *x,int n,int rev)
{
int i,j,k,ds;
ll w,u,v;
for(i=1,j=n>>1,k=n>>1;i<n-1;i++,k=n>>1)
{
if(i<j) swap(x[i],x[j]);
while(j>=k) j-=k,k>>=1;
if(j<k) j+=k;
}
for(i=2,ds=1;i<=n;i<<=1,ds++)
{
for(j=0;j<n;j+=i)
{
w=1;
for(k=j;k<j+i/2;k++)
{
u=x[k];
v=Mul(w,x[k+i/2]);
x[k]=(u+v)%MOD;
x[k+i/2]=(u-v+MOD)%MOD;
w=Mul(w,wn[ds]);
}
}
}
if(rev==-1)
{
for(i=1;i<n/2;i++) swap(x[i],x[n-i]);
w=Qpow(n,MOD-2,MOD);
for(i=0;i<n;i++) x[i]=Mul(x[i],w);
}
}
int main()
{
Getwn();
while(~scanf("%d%d",&n,&m))
{
for(int i=0;i<n;i++)scanf("%lld",&a[i]);
for(int i=0;i<m;i++)scanf("%lld",&b[i]);
int len=1,s=n+m;
while(len<s)len<<=1;
for(int i=n;i<len;i++)a[i]=0;
for(int i=m;i<len;i++)b[i]=0;
NTT(a,len,1);NTT(b,len,1);
for(int i=0;i<len;i++)a[i]=Mul(a[i],b[i]);
NTT(a,len,-1);
for(int i=0;i<=s;i++)printf("%lld ",a[i]);puts("");
}
}
相关文章推荐
- Poj 3070 Fibonacci (矩阵快速幂)
- 7_13_F题 K Best(二分、最大化平均值)
- Java 面试题和答案 - (下)
- Sticks
- Leetcode #3 Longest Substring Without Repeating Characters
- 深入分析AsyncTask
- yii框架循环添加只能加入最后一条的解决办法
- Find the difference——Difficulty:Easy
- 7_13_E题 Pie(二分)
- HBase协处理器
- SourceTree windows版本免注册免登陆使用方法
- 【NOIP模拟】树上摩托
- 7_13_B题 Boonie and Clyde(tarjan求割点)
- 7_13_A题 SPF (tarjan求割点)
- NOIP提高组模拟 树上摩托
- 智能硬件开发如何选择低功耗MCU?
- 【读书笔记】《Web全栈工程师的自我修养》
- 7_11_I题 Gems Fight!(状压dp)
- Android手势识别
- 7_11_ H题 Rabbit Kingdom(容斥+树状数组)