好奇心害死猫——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.


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值