其实我本来想把这篇东西接在那个《论二分法的利处》后面来着,后来想想还是算了……
本来这东西应该可以用压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.