1. 程式人生 > >洛谷P1919 A*B problem 快速傅裏葉變換模板 [FFT]

洛谷P1919 A*B problem 快速傅裏葉變換模板 [FFT]

sca 快速 https -o ora stream ros for AR

  題目傳送門

A*B problem

題目描述

給出兩個n位10進制整數x和y,你需要計算x*y。

輸入輸出格式

輸入格式:

第一行一個正整數n。 第二行描述一個位數為n的正整數x。 第三行描述一個位數為n的正整數y。

輸出格式:

輸出一行,即x*y的結果。(註意判斷前導0)

輸入輸出樣例

輸入樣例#1:
1
3
4
輸出樣例#1:
12

說明

數據範圍:

n<=60000

來源:bzoj2179

本題數據為洛谷自造數據,使用CYaRon耗時5分鐘完成數據制作。


  分析:

  之前都是拿python水過這題的。今天學懂了FFT,特地來刷一波。

  思路沒什麽講的,就是FFT,不過註意前導零,還要註意有的位數上會大於10,需要處理。

  Code:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<cstdlib>
 4 #include<cmath>
 5 #include<algorithm>
 6 #include<iostream>
 7 #include<iomanip>
 8 using namespace std;
 9 const double pi=acos(-1.0
); 10 const int N=5e5+7; 11 int n,m,L,c[N],r[N]; 12 char ca[N],cb[N]; 13 struct complex{ 14 double x;double y; 15 complex(double xx=0,double yy=0){x=xx;y=yy;} 16 }w1[N],w2[N]; 17 complex operator + (complex a,complex b){return complex(a.x+b.x,a.y+b.y);} 18 complex operator - (complex a,complex b){return
complex(a.x-b.x,a.y-b.y);} 19 complex operator * (complex a,complex b){return complex(a.x*b.x-a.y*b.y,a.x*b.y+b.x*a.y);} 20 void FFT(complex *A,int flag) 21 { 22 for(int i=0;i<n;i++) 23 if(i<r[i])swap(A[i],A[r[i]]); 24 for(int i=1;i<n;i<<=1){ 25 complex wn(cos(pi/i),flag*sin(pi/i)); 26 for(int j=0;j<n;j+=(i<<1)){ 27 complex w(1,0); 28 for(int k=0;k<i;k++,w=w*wn){ 29 complex a=A[j+k],b=w*A[i+j+k]; 30 A[j+k]=a+b,A[i+j+k]=a-b;} 31 } 32 } 33 } 34 int main() 35 { 36 scanf("%d",&n);n--;m=2*n; 37 scanf("%s",ca); 38 for(int i=0;i<=n;i++)w1[i].x=ca[n-i]-0; 39 scanf("%s",cb); 40 for(int i=0;i<=n;i++)w2[i].x=cb[n-i]-0; 41 for(n=1;n<=m;n<<=1)++L; 42 for(int i=0;i<n;i++) 43 r[i]=((r[i>>1]>>1)|((i&1)<<(L-1))); 44 FFT(w1,1);FFT(w2,1); 45 for(int i=0;i<=n;i++)w1[i]=w1[i]*w2[i]; 46 FFT(w1,-1); 47 for(int i=0;i<=m;i++)c[i]=(int)(w1[i].x/n+0.5); 48 for(int i=0;i<=m;i++) 49 if(c[i]>=10){ 50 c[i+1]+=c[i]/10;c[i]%=10; 51 if(i==m)m++;} 52 while(m>0&&c[m]==0)m--; 53 for(int i=m;i>=0;i--)printf("%d",c[i]); 54 return 0; 55 }

洛谷P1919 A*B problem 快速傅裏葉變換模板 [FFT]