BZOJ_2179_FFT快速傅立叶_(FFT)

描述


http://www.lydsy.com/JudgeOnline/problem.php?id=2179

超大整数乘法

 

分析


FFT模板题.

把数字看成是多项式,x是10.然后用FFT做多项式乘法,最后进位就好了.

 

注意:

1.进位前要把每一位加0.5(或者更小),然后向下取整,应该是浮点数的计算误差吧...

 

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int maxn=140000;
 5 const double pi=acos(-1.0);
 6 int len;
 7 int rev[maxn],ans[maxn];
 8 char str[maxn];
 9 struct cp{//复数(complex)
10     double r,i;
11     cp(double r_=0.0,double i_=0.0):r(r_),i(i_){}
12     cp operator + (const cp &x) const { return cp(r+x.r,i+x.i); }
13     cp operator - (const cp &x) const { return cp(r-x.r,i-x.i); }
14     cp operator * (const cp &x) const { return cp(r*x.r-i*x.i,r*x.i+i*x.r); }
15 }a[maxn],b[maxn],A[maxn];
16 void brc(int &len){//二进制逆序置换(bit-reverse-copy)
17     memset(rev,-1,sizeof rev);
18     int k=1,l=0;
19     while(k<len) k<<=1,l++;
20     len=k;
21     rev[0]=0; rev[len-1]=len-1;
22     for(int i=1;i<len-1;i++){
23         if(rev[i]!=-1) continue;
24         int x=i,y=0,m=l;
25         while(m--) y<<=1, y|=(x&1), x>>=1;
26         rev[i]=y; rev[y]=i;
27     }
28 }
29 void dft(cp *a,int n,int flag){//离散傅里叶变换(discrete-Fourier-transform)
30     for(int i=0;i<n;i++) A[rev[i]]=a[i];
31     for(int i=0;i<n;i++) a[i]=A[i];
32     for(int m=2;m<=n;m<<=1){
33         cp wn(cos(2.0*pi/m*flag),sin(2.0*pi/m*flag));
34         for(int i=0;i<n;i+=m){
35             cp w(1.0,0.0); int k=m>>1;
36             for(int j=0;j<k;j++){
37                 cp t=w*a[i+j+k], u=a[i+j];
38                 a[i+j]=u+t;
39                 a[i+j+k]=u-t;
40                 w=w*wn;
41             }
42         }
43     }
44     if(flag==-1)for(int i=0;i<n;i++) a[i].r/=n;
45 }
46 void readin(cp *a){
47     scanf("%s",str);
48     int l=strlen(str);
49     for(int i=0;i<l;i++) a[i].r=str[l-1-i]-'0';
50 }
51 int main(){
52     scanf("%d",&len);
53     len=len*2-1;
54     readin(a); readin(b);
55     brc(len);
56     dft(a,len,1); dft(b,len,1);
57     for(int i=0;i<len;i++) a[i]=a[i]*b[i];
58     dft(a,len,-1);
59     for(int i=0;i<len;i++) ans[i]=a[i].r+0.5;
60     for(int i=0;i<len;i++) ans[i+1]+=ans[i]/10, ans[i]%=10;
61     len++;
62     while(!ans[len]&&len) len--;
63     for(int i=len;i>=0;i--) printf("%d",ans[i]);
64     return 0;
65 }
View Code

 

 

2179: FFT快速傅立叶

Time Limit: 10 Sec  Memory Limit: 259 MB
Submit: 2567  Solved: 1308
[Submit][Status][Discuss]

Description

给出两个n位10进制整数x和y,你需要计算x*y。

Input

第一行一个正整数n。 第二行描述一个位数为n的正整数x。 第三行描述一个位数为n的正整数y。

Output

输出一行,即x*y的结果。

Sample Input

1
3
4

Sample Output

12

数据范围:
n<=60000

HINT

Source

posted @ 2016-06-10 17:24  晴歌。  阅读(419)  评论(1编辑  收藏  举报