bzoj2179: FFT快速傅立叶

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 #include <cmath>
 6 using namespace std;
 7 const double PI=acos(-1);
 8 const int maxn=250005;
 9 int n,len,m,rev[maxn],ans[maxn];
10 struct node{
11     double real,imag;
12     node operator +(const node &x){return (node){real+x.real,imag+x.imag};}
13     node operator -(const node &x){return (node){real-x.real,imag-x.imag};}
14     node operator *(const node &x){return (node){real*x.real-imag*x.imag,real*x.imag+imag*x.real};}
15 }a[maxn],b[maxn],c[maxn],w,wn,t1,t2;
16 void read(int &x){
17     x=0; int f=1; char ch;
18     for (ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') f=-1;
19     for (;isdigit(ch);ch=getchar()) x=x*10+ch-'0'; x*=f;
20 }
21 void Read(node *a){
22     char ch;
23     for (int i=m-1;i>=0;i--){
24         for (ch=getchar();!isdigit(ch);ch=getchar());
25         a[i].real=(double)(ch-'0'); 
26     }
27 }
28 int Rev(int x){
29     int temp=0;
30     for (int i=0;i<len;i++) temp<<=1,temp+=(x&1),x>>=1;
31     return temp;
32 }
33 void FFT(node *a,int op){
34     for (int i=0;i<n;i++) if (i<rev[i]) swap(a[i],a[rev[i]]);
35     for (int s=2;s<=n;s<<=1){
36         wn=(node){cos(op*2*PI/s),sin(op*2*PI/s)};
37         for (int i=0;i<n;i+=s){
38             w=(node){1,0};
39             for (int j=i;j<i+s/2;j++,w=w*wn){
40                 t1=a[j],t2=w*a[j+s/2];
41                 a[j]=t1+t2,a[j+s/2]=t1-t2;
42             }
43         }
44     }
45 }
46 int main(){
47     read(m); n=1,len=0;
48     while (n<(m<<1)) n<<=1,len++;
49     Read(a),Read(b);
50     for (int i=0;i<n;i++) rev[i]=Rev(i);
51     FFT(a,1),FFT(b,1);
52     for (int i=0;i<n;i++) c[i]=a[i]*b[i];
53     FFT(c,-1);
54     for (int i=0;i<n;i++) ans[i]=(int)round(c[i].real/n);
55     for (int i=0;i<n;i++) ans[i+1]+=ans[i]/10,ans[i]=ans[i]%10;
56     int j; for (j=n-1;j>=0;j--) if (ans[j]) break;
57     if (j==-1) puts("0");
58     else{for (;j>=0;j--) printf("%d",ans[j]);puts("");}
59     return 0;
60 }
View Code

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2179

题目大意:给定两个大数a,b,求a*b,位数n<=60000;

做法:FFT入门题,FFT的做法可以自己去看算法导论,这题是裸的卷积,直接上DFT或者NTT,我贴的是DFT的。

posted @ 2016-09-16 23:32  oyzx~  阅读(126)  评论(0编辑  收藏  举报