其實我本來想把這篇東西接在那個《論二分法的利處》後面來着,後來想想還是算了……
本來這東西應該可以用壓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.