好奇心害死貓——codevs3123超大整數乘法

其實我本來想把這篇東西接在那個《論二分法的利處》後面來着,後來想想還是算了……

本來這東西應該可以用壓9位(10位?)的高精度暴力做的,但是總覺得不太好(天梯分類是高精度加強,再交個暴力高精度乘法就沒意思了對吧),結果一看題解,對裏面的人提到的FFT很感興趣,然後……我就用相當於(1/貓的細胞數)的好奇心把自己害了……

其實FFT在這題裏的應用不過就是把兩個數的乘積變成了兩個多項式(多項式用一些點表示)相乘的形式(雖說具體怎麼變我是不知道的……)FFT起的作用就是二分求解多項式乘積,這一做法時間複雜度爲O(n log n)。

足足兩天半糾結了以後我才發現我在糾結的其實是ans該用longint數組還是int64數組儲存…………

上代碼:

const unitdigit=4;
      unitsize=10000;
      maxlen=250000 div 4;
type point=record
     x,y:extended;
     end;
     poly=array[0..1 shl 17]of point;
var  ans:array[0..maxlen]of int64;
     a,b,w,tt:poly;
     n,i,j,p,k:longint;
     s,st,ss:ansistring;
     wt:point;
function mul(a,b:point):point;
var c:point;
begin
  c.x:=a.x*b.x-a.y*b.y;
  c.y:=a.x*b.y+a.y*b.x;
  exit(c);
end;
function add(a,b:point):point;
var c:point;
begin
  c.x:=a.x+b.x;
  c.y:=a.y+b.y;
  exit(c);
end;
function minus(a,b:point):point;
var c:point;
begin
  c.x:=a.x-b.x;
  c.y:=a.y-b.y;
  exit(c);
end;
procedure fft(var a:poly;s,t:longint);
begin
  if n shr t=1 then exit;
  fft(a,s,t+1);
  fft(a,s+1 shl t,t+1);
  for i:=0 to n shr(t+1)-1 do
  begin
    p:=i shl(t+1)+s;
    wt:=mul(w[i shl t],a[p+1 shl t]);
    tt[i]:=add(a[p],wt);
    tt[i+n shr(t+1)]:=minus(a[p],wt);
  end;
  for i:=0 to n shr t-1 do
  a[i shl t+s]:=tt[i];
end;
procedure change(var a:poly;s:ansistring);
var i,code,len:longint;
begin
  while length(s) mod unitdigit<>0 do
  insert('0',s,0);
  len:=length(s) div unitdigit;
  for i:=1 to len do
  val(copy(s,i*unitdigit-unitdigit+1,unitdigit),a[len-i].x);
  while n shr 1<len do n:=2*n;
end;
procedure print;
var i,j:longint;
    s:ansistring;
begin
  for i:=k downto 0 do
  begin
    str(ans[i],s);
    while (k<>i)and(length(s)<4) do s:='0'+s;
    write(s);
  end;
  writeln;
end;
begin
  n:=1;
  readln(s);
  ss:=copy(s,1,pos(' ',s)-1);
  delete(s,1,pos(' ',s));
  st:=s;
  change(a,ss);
  change(b,st);
  for i:=0 to n-1 do
  begin
    w[i].x:=cos(pi*2*i/n);
    w[i].y:=sin(pi*2*i/n);
  end;
  fft(a,0,0);
  fft(b,0,0);
  for i:=0 to n-1 do
  begin
    a[i]:=mul(a[i],b[i]);
    w[i].y:=-w[i].y;
  end;
  fft(a,0,0);
  for k:=0 to n-1 do
  begin
    ans[k]:=ans[k]+round(a[k].x/n);
    ans[k+1]:=ans[k] div unitsize;
    ans[k]:=ans[k] mod unitsize;
  end;
  while (ans[k]=0)and(k>0) do
  dec(k);
  print;
end.


發佈了35 篇原創文章 · 獲贊 0 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章