题目描述 Description

    给出两个正整数A和B,计算A*B的值。保证A和B的位数不超过100000位。

输入描述 Input Description

    读入两个用空格隔开的正整数

输出描述 Output Description

    输出A*B的值

样例输入 Sample Input

    4 9

样例输出 Sample Output

    36

数据范围及提示 Data Size & Hint

    两个正整数的位数不超过100000位

什么都不说了,裸FFT

看了一天的算导,勉强看懂了怎么O(nlogn)求dft,求dft^(-1)就实在看不懂了,唉,只好记下结论

首先是理解系数表达和点值表达,因为点值表达乘法是O(n)的,所以我们要通过系数表达算出点值表达,相乘后再算出点值表达

这个是分治求的dft奇偶分成两个序列,分别求出这两个序列的dft然后通过下面的代码就可以O(n)合并这个两个dft了

1 for i:=0 to n>>(t+1)-1 do
2   begin
3     p:=i<<(t+1)+s;
4     wt:=w[i<<t]*a[p+1<<t];
5     tt[i]:=a[p]+wt;
6     tt[i+n>>(t+1)]:=a[p]-wt;
7   end;

先把单位根的几个性质搞懂,然后就基本上可以理解这个分治了(最好是自己手算一下......我就懒得说什么了,自己都不是很理解,代码还是抄别人的)

zky神犇手动搬运算导FFT

pascal代码(我从这里抄的)

  1 const
  2         s=4;
  3 type
  4         cp=record
  5           x,y:double;
  6         end;
  7         arr=array[0..1 shl 17]of cp;
  8 var
  9         c:array[0..100000]of int64;
 10         a,b,w,tt:arr;
 11         n,i,p:longint;
 12         st:ansistring;
 13         wt:cp;
 14 
 15 operator *(var a,b:cp)c:cp;
 16 begin
 17         c.x:=a.x*b.x-a.y*b.y;
 18         c.y:=a.x*b.y+a.y*b.x;
 19 end;
 20 
 21 operator +(var a,b:cp)c:cp;
 22 begin
 23         c.x:=a.x+b.x;
 24         c.y:=a.y+b.y;
 25 end;
 26 
 27 operator -(var a,b:cp)c:cp;
 28 begin
 29         c.x:=a.x-b.x;
 30         c.y:=a.y-b.y;
 31 end;
 32 
 33 procedure dft(var a:arr;s,t:longint);
 34 begin
 35         if n>>t=1 then exit;
 36         dft(a,s,t+1);
 37         dft(a,s+1<<t,t+1);
 38         for i:=0 to n>>(t+1)-1 do
 39           begin
 40             p:=i<<(t+1)+s;
 41             wt:=w[i<<t]*a[p+1<<t];
 42             tt[i]:=a[p]+wt;
 43             tt[i+n>>(t+1)]:=a[p]-wt;
 44           end;
 45         for i:=0 to n>>t-1 do
 46           a[i<<t+s]:=tt[i];
 47 end;
 48 
 49 procedure get(var a:arr);
 50 var
 51         i,l,ll:longint;
 52         c:char;
 53 begin
 54         read(c);
 55         st:='';
 56         while (ord(c)>=ord('0')) and (ord(c)<=ord('9')) do
 57           begin
 58             st:=st+c;
 59             read(c);
 60           end;
 61         while length(st)mod s<>0 do
 62           insert('0',st,0);
 63         ll:=length(st)div s;
 64         for l:=1 to ll do
 65           val(copy(st,l*s-s+1,s),a[ll-l].x);
 66         while n>>1<l do
 67           n:=n<<1;
 68 end;
 69 
 70 begin
 71         n:=1;
 72         get(a);
 73         get(b);
 74         for i:=0 to n-1 do
 75           w[i].x:=cos(pi*2*i/n);
 76         for i:=0 to n-1 do
 77           w[i].y:=sin(pi*2*i/n);
 78         dft(a,0,0);
 79         dft(b,0,0);
 80         for i:=0 to n-1 do
 81           a[i]:=a[i]*b[i];
 82         for i:=0 to n-1 do
 83           w[i].y:=-w[i].y;
 84         dft(a,0,0);
 85         for i:=0 to n-1 do
 86           begin
 87             c[i]:=c[i]+round(a[i].x/n);
 88             c[i+1]:=c[i] div 10000;
 89             c[i]:=c[i] mod 10000;
 90           end;
 91         while (c[i]=0) and (i>0) do
 92           dec(i);
 93         for p:=i downto 0 do
 94           begin
 95             str(c[p],st);
 96             while (i<>p) and (length(st)<s) do
 97               st:='0'+st;
 98             write(st);
 99           end;
100 end.
View Code

相关文章:

  • 2019-07-16
  • 2021-11-13
  • 2022-12-23
  • 2021-06-15
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
猜你喜欢
  • 2021-11-20
  • 2021-10-13
  • 2022-03-05
  • 2021-05-23
  • 2021-12-17
  • 2021-05-16
  • 2021-10-19
相关资源
相似解决方案