BZOJ 2194 快速傅里叶之二
2194: 快速傅立叶之二
Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 1471 Solved: 855
[Submit][Status][Discuss]
Description
请计算C[k]=sigma(a[i]*b[i-k]) 其中 k < = i < n ,并且有 n < = 10 ^ 5。 a,b中的元素均为小于等于100的非负整数。
Input
第一行一个整数N,接下来N行,第i+2..i+N-1行,每行两个数,依次表示a[i],b[i] (0 < = i < N)。
Output
输出N行,每行一个整数,第i行输出C[i-1]。
Sample Input
5
3 1
2 4
1 1
2 4
1 4
3 1
2 4
1 1
2 4
1 4
Sample Output
24
12
10
6
1
12
10
6
1
HINT
Source
和上题一样啊,脑补一下小结论
#include <bits/stdc++.h> #define ll long long using namespace std; typedef complex <double> E; inline int read(){ int x=0;int f=1;char ch=getchar(); while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} return x*f; } const int MAXN=1e6+10; const double pi=acos(-1); int n,m,R[MAXN],L,H; E a[MAXN],b[MAXN],w[MAXN],k; inline void FFT(E *a,int f){ for(int i=0;i<L;i++){ if(i<R[i]) swap(a[i],a[R[i]]); } for(int len=2;len<=L;len<<=1){ int l=len>>1; E wn(cos(pi/l),f*sin(pi/l)); for(int i=1;i<l;i++) w[i]=w[i-1]*wn; for(int st=0;st<L;st+=len){ for(int k=0;k<l;k++){ E x=a[st+k];E y=w[k]*a[st+k+l]; a[st+k]=x+y;a[st+k+l]=x-y; } } } if(f==-1){ for(int i=0;i<L;i++){ a[i]/=L; } } } int main(){ //freopen("All.in","r",stdin); //freopen("bai.out","w",stdout); n=read();w[0].real()=1; for(int i=0;i<n;i++){ a[i]=read();b[n-i-1]=read(); } L=1; while(L<2*n) L<<=1,H++; for(int i=0;i<L;i++){ R[i]=(R[i>>1]>>1)|((i&1)<<(H-1)); } FFT(a,1);FFT(b,1); for(int i=0;i<L;i++) a[i]=a[i]*b[i]; FFT(a,-1); for(int i=0;i<n;i++) printf("%d\n",int(a[i+n-1].real()+0.5)); return 0; }
对拍代码
#include <bits/stdc++.h> using namespace std; int main(){ srand(time(int(NULL))); freopen("All.in","w",stdout); int n=rand()%10007;int m=rand()%10007; cout<<n<<' '<<m<<endl; for(int i=0;i<n;i++){ printf("%d\n",rand()%17+2); } for(int i=0;i<m;i++){ printf("%d\n",rand()%17+2); } return 0; }