快速乘法

AI权益加码!Claude Code、Cursor等20+工具免费用! 购周边限时加赠Coding Plan Lite,畅享主流AI工具!学习进阶更高效! 阅读详情

快速乘法

 

 

 

先让我们看abcd是怎样进行的:

 

 

 

ab

 

 

 

*             cd  

 

 

 

adR+bd

 

 

 

acR2+bcR           

 

 

 

acR2+(ad+bc)R+bd        (R是进位制, 下同.)

 

 

 

可见进行了四次乘法.

更一般地, 两个 n 位数相乘, 要进行 n2 次单位乘法.

在上面的过程中, 似乎我们觉得这个算法并没有做任何多余的事情, 因为我们必须考虑每一组,它们的乘积对最终的结果都会产生影响. 而且我们不能通过调整计算顺序从根本上降低算法时间复杂度, 至多只能使其常数因子稍小一些.

要改进乘法速度就要设法减少乘法次数!

减少的途径, 主要有两种:

 

 

 

1.  二分法

 

 

 

2.  快速傅立叶变换

 

 

 

二分法

 

 

 

1. 用代数式的变换可得:

 

 

 

   ab*cd = acR2+(ad+bc)R+bd = acR2 + [(a-d)(b-c)+ac+bd]R + bd

 

 

 

可见只进行了3次乘法.

 

 

 

由此联想到用递归来做, 得下示算法 (n 应是2的正整数次幂):

 

 

 

function MULT(X, Y, n); { X Y 2 个小于 2n 的整数, 返回结果为 X Y 的乘积 XY }
begin
  if n=1 then
     if (X=1)and(Y=1) then return(S)  else return(0)

 

 

 

else begin

 

 

 

A:=X的左边n/2;

 

 

 

B:=X的右边n/2;

 

 

 

C:=Y的左边n/2;

 

 

 

D:=Y的右边n/2;

 

 

 

ml:=MULT(A,C,n/2);

 

 

 

m2:=MULT(A-B,D-C,n/2);

 

 

 

m3:=MULT(B,D,n/2);

 

 

 

S:=S*(m1*2n+(m1+m2+m3)*2n/2+m3);

 

 

 

return(S);

 

 

 

end;

 

 

 

end;

 

 

 

它的时间复杂度是 O(nlog3)≈O(n1.59).

 

 

 

2. 也可以将大数分为三部分:

 

 

 

abc*def=(ad)R4+(ae+bd)R3+(af+be+cd)R2-(bf+ce)R-cf

 

 

 

=adR4 + [(a-b)(e-d)+ad+be]R3 + [(a-c)(f-d)+ad+cf+be]R2 + [(b-c)(f-e)+be+cf]R + cf

 

 

 

  分成更多部分也行, 例如 4 部分:

 

 

 

abcd*efgh=aeR6+(af+be)R5+(ag+bf+ce)R4+(ah+bg+cf+de)R3+(bh+cg+df)R2+(ch+dg)R+dh

 

 

 

=aeR6 + [(a-b)(f-e)+ae+bf]R5+[(a-c)(g-e)+ae+cg+be]R4 +

 

 

 

[(a-b+c-d)(h-g+f-e)-(af+be)+(ag+bf+ce)+(bh+cg+df)-(ch+dg)+ae+dh]R3 +

 

 

 

[(b-d)(h-f)+bf+dh+cg]R2 + [(c-d)(h-g)+cg+dh]R + dh

 

 

 

观察发现斜体字部分正好是 R5, R4, R2, R 项的系数(画线部分).这对优化有很大帮助, 使得实际上只需进行 9 次乘法(而不是 42=16 ). 但是, 分成更多部分, 递归的空间消耗迅猛增加. 且算式复杂.

 

 

 

2. 快速傅立叶变换  (FFT)

 

 

 

----翻译,修改自 Mathematical Constants and computation 

FFT based multiplication of large numbers

两个大整数可写成如下形式:  X=P(B), Y=Q(B) . B是基数 (通常 B = 10 10 的正整数次方) 可以看作 P , Q  是两个多项式:

 

 

 

 

 

 

   有它们的乘积 R(z), 那么 XY=R(B). 这样, 问题转为求两个多项式的乘积.而一个不超过 m 次的多项式可以用m个点 ( zm个不同值时的R(z) ) 来表示. 并且适当的点值表示的多项式相乘可以在O(n) 的时间里完成. 问题是怎样把多项式快速转为点值表示法.

 

 

 

mz应取1的单位复数根Wk.

 

 

 

 

 

 

这样一来, 变换可以在 O(n logn) 的时间里完成.

 

 

 

2.1 Fourier 变换

 

 

 

设有序列 A = (a0, a1,¼, a2n-1), 对它进行 Fourier 变换, 方法如下.

 

 

 

 

 

 

Fourier 变换:

 

 

 

 

 

 

由于 , 所以进行正反两次Fourier 变换后, 结果应除以 2n.

 

 

 

直接按定义计算显然低效.

 

 

 

 

 

 

2.2  快速傅立叶变换(Fast Fourier Transform, FFT)

 

 

 

快速傅立叶变换是一个在O(n logn)里计算序列 Fourier Transform 的方法 

 

 

 

由于公式:

 

 

 

 

 

 

 

由此在O(n logn)里计算F2n(A) 的步骤:

 

 

 

A为两部分.

 

 

 

A0 = (a0, a2,…, a2n-2), A1 = (a1,a3,…,a2n-1).

 

 

 

递归,计算傅立叶变换:

 

 

 

C = Fn(A0) = (c0,c1,...,cn-1), D = Fn(A1) = (d0,d1,...,dn-1).

 

 

 

合并序列, B = (b0,...,b2n-1) = F2n(A)

 

 

 

bk = ck + wk dk,    bn+k = ck - wk dk,    0 ≤ k < n

 

 

 

 

 

 

 

 

 

2.3  FFT 乘法

 

 

 

n 2的幂. 且两个大整数 X & Y 的系数小于n

 

 

 

 

 

 

在时间 O(nlog(n)), 计算 Z = XY 在时间 O(nlog(n)), 执行下列步骤 :

 

 

 

计算 大小为 2n 傅立叶变换 X* 的序列 (xj) :

 

 

 

X* = (x0*,x1*,...,x2n-1*)= F2n(x0,x1,...,xn-1,0,...,0)

 

 

 

同样, 计算 Y* 傅立叶变换(yj) :

 

 

 

Y* = (y0*,y1*,...,y2n-1*) = F2n(y0,y1,...,yn-1,0,....,0)

 

 

 

计算 X*, Y* 对应项的乘积到 Z*

 

 

 

Z* = (z0*,z1*,...,z2n-1*),      zi*xi* yi*

 

 

 

计算 Z* 的反傅立叶变换 Z, 并将各项除以 2n.

 

 

 

 

 

 

然后重新整理系数zi到正常格式,

 

 

 

这么做等于计算 Z = XY.

 

 

 

注意在X的系数后添加高次零项使n化为2的正整数次幂, Y也是.

 

 

 

可见, 进行了3次大小2nFFT, 和一组系数相乘(可忽略), 因此它的复杂度是3次大小2nFFT.

 

 

 

计算平方时,只需进行2次大小2nFFT.

 

 

 

让我们来看一个具体实例(100进制): 45672=

 

 

 

     0   1    2   3

 

 

 

A =(45  67  00  00)      { 补零 }

 

 

 

45,00   67,00         { 分成奇,偶两组 }

 

 

 

  0   1   2   3

 

 

 

45  00  67  00         { 每组再分成奇,偶两组.分组完成 }

 

 

 

      0      1

 

 

 

45,45  67,67            { 开始变换: bk = ck + wk dk,    bn+k = ck - wk dk }

 

 

 

112,      45+67i ,  -22,       45-67i  { 变换完毕 }

 

 

 

12544, -2464+6030i,  484, -2464-6030i  {各项平方}

 

 

 

12544,484   -2464+6030i ,-2464-6030i {分成奇,偶两组}

 

 

 

12544   484   -2464+6030i   -2464-6030i  { 每组再分成奇,偶两组.分组完成 }

 

 

 

13028, 12060   -4928,12060i  { 反FFT bk = ck + w -k dk,    bn+k = ck - w -k dk }

 

 

 

8100,  24120,  17956,     0    { 变换完毕 }

 

 

 

2025,  6030,    4489,     0      { 各项除以四 }

 

 

 

2025

 

 

 

  6030

 

 

 

     4489

 

 

 

20857489              { 加起来 }

 

 

 

再用计算器验算一下, 没错吧!

 

 

 

2.2 数字错误

 

 

 

note: 由于 wk 不可能精确储存(涉及无理数), 所以会产生误差, 当误差 <0.5 时, 可以容忍, <0.25 时最好.

///////////////////////////////////////

涉及程序:

{$N+}
{D-,E+,F-,G+,I-,L-,P+,X+,Y-}
{Q-,R-,S-,T-,V-}
{M 65520,0,655360}
Program FFTMul;
Uses dos;
Const MaxSize=1 shl 4; pi=3.141592653589793238; Bas=100000; LBas=5; invBas=1/Bas;
type complex=record
         i,r:Extended;
        end;
Var i, j, k, n, asize, bSize :Longint;
    WorstEr{, MaxNum }:Extended;
    aCoef, bCoef, ccoef :Array[0..Pred(MaxSize)] of LongInt;
    Time1,Time2,th2,tm2,ts2,tms2,th1,tm1,ts1,tms1:Word;

Procedure Initial(Var w:Array of Complex; Var lst:Array of word; n:LongInt);
 Var i, j, n2, m :LongInt;
     tmp :Extended;
 Begin
   i:=0;
   tmp:=2*pi/n;
   n2:=n shr 2;
   For i:=0 to n2 do Begin
     w[i].i:=sin(tmp*i);
     w[i].r:=Sqrt(1-sqr(w[i].i));
   End;
   i:=Pred(n2);   j:=succ(n2);
   While i>=0 do Begin
     w[j].i:= w[i].i;
     w[j].r:=-w[i].r;
     Dec(i);  Inc(j);
   End;
   n2:=n;  lst[0]:=0;  m:=1;   i:=1;
   While n2<>1 do Begin
     n2:=n2 shr 1;
     m :=m  shl 1;
     j:=0;
     While i<m do Begin
       lst[i]:=lst[j]+n2;
       inc(i);  inc(j);
     End;
   End;
 End;

Procedure PZero(x:LongInt);
 Begin
   Inc(x);
   While x<(Bas*0.1) do Begin
     Write('0');
     x:=x*10;
    End;
 End;

Procedure Print(a:Array of LongInt; n:LongInt);
 Var i :LongInt;
 Begin
   Write (a[0]);
   For i:=1 to pred(n) do begin
     PZero (a[i]);
     Write (a[i]);
   end;
 End;

Procedure FFT(Const a:Array of Complex; Var b:Array of Complex;Const w:Array of Complex;Const lst:Array of Word; n:Longint);
 Var per, m, n2, n1, j, k, i2, p :LongInt;
     tmp1, tmp2 :Extended;
     Tmpb, Tmpb2 :Complex;
 Begin
   For j:=0 to pred(n) do  b[j]:=a[lst[j]];
   n2:=1;  per:=1;
   n1:=n shr 1;
   While per<n do Begin
     m:=n2;  j:=0;  k:=n2;
     per:=per shl 1;
     While k<n do Begin
       i2:=0;
       While j<m do Begin
         Tmpb:=b[j];
         Tmp1:=b[k].r*w[i2].r-b[k].i*w[i2].i;
         Tmp2:=b[k].r*w[i2].i+b[k].i*w[i2].r;
         b[j].r:=Tmpb.r+Tmp1;
         b[j].i:=Tmpb.i+Tmp2;
         b[k].r:=Tmpb.r-Tmp1;
         b[k].i:=Tmpb.i-Tmp2;
         Inc(j);   Inc(k);   Inc(i2,n1);
       End;
       Inc(m, per);  Inc(j, n2);  Inc(k, n2);
     End;
     n2:=per;
     n1:=n1 shr 1;
   End;
 End;

Procedure invFFT(Const a:Array of Complex; Var b:Array of Complex;Const w:Array of Complex;Const lst:Array of Word; n:Longint);
 Var per, m, n1, n2, j, k, i2 :LongInt;
     Tmp1, Tmp2 :Extended;
     Tmpb :Complex;
 Begin
   For j:=0 to pred(n) do  b[j]:=a[lst[j]];
   n2:=1;  per:=1;
   n1:=n shr 1;
   While per<n do Begin
     m:=n2;  j:=0;  k:=n2;
     per:=per shl 1;
     While k<n do Begin
       i2:=0;
       While j<m do Begin
         Tmpb:=b[j];
         Tmp1:=b[k].r*w[i2].r+b[k].i*w[i2].i;
         Tmp2:=b[k].r*w[i2].i-b[k].i*w[i2].r;
         b[j].r:=Tmpb.r+Tmp1;
         b[j].i:=Tmpb.i-Tmp2;
         b[k].r:=Tmpb.r-Tmp1;
         b[k].i:=Tmpb.i+Tmp2;
         Inc(j);  Inc(k);  Inc(i2,n1);
       End;
       Inc(m, per);  Inc(j, n2);  Inc(k, n2);
     End;
     n2:=per;
     n1:=n1 shr 1;
   End;
   Tmp1:=1/n;
   For j:=0 to pred(n) do
     b[j].r:=b[j].r*Tmp1;
 End;

Procedure MulFFT(Const ACoef:Array of LongInt; ASize:LongInt;Const BCoef:Array of LongInt; BSize:LongInt;
                   Var CCoef:Array of LongInt);
 Var a, b, tmp :Array[0..MaxSize] of complex;
     lst :Array[0..pred(MaxSize)] of Word;
     w   :Array[0..MaxSize shr 1] of complex;
     n, i :LongInt;
     logn :Byte;
     TmpR, num{,maxr,maxi }:Extended;
 Begin
   n:=1;
   logn:=0;
   while n<(aSize+bSize) do Begin n:=n shl 1; Inc(logn); End;
   Initial(w,lst,n);
   for i:=0 to ASize do Begin
     a[i].r:=ACoef[i];
     a[i].i:=0;
   End;
   for i:=asize to n do Begin
     a[i].r:=0;   a[i].i:=0;
   End;
   for i:=0 to BSize do Begin
     b[i].r:=BCoef[i];
     b[i].i:=0;
   End;
   for i:=bsize to n do Begin
     b[i].r:=0;   b[i].i:=0;
   End;
{   maxr:=0;
   maxi:=0;}
   FFT(a, b, w, lst, n);
   FFT(b, tmp, w,lst, n);
   For i:=0 to pred(n) do Begin
     a[i].r:=tmp[i].r*b[i].r - tmp[i].i*b[i].i;
     a[i].i:=tmp[i].r*b[i].i + tmp[i].i*b[i].r;
   End;
   invFFT(a, b, w, lst, n);
{   For i:=0 to pred(n) do if Abs(b[i].r)>Maxr then maxr:=Abs(b[i].r);
   For i:=0 to pred(n) do if Abs(b[i].i)>Maxi then maxi:=Abs(b[i].i);}
   TmpR:=0;
   For i:=pred(n) downto 1 do Begin
     num:=b[pred(i)].r+TmpR;
     TmpR:=Int((num+0.1)*invBas);
     CCoef[i]:=Round(num-TmpR*Bas);
     If ABS(num-TmpR*Bas-CCoef[i]) > WorstEr Then WorstEr:=Abs((num-TmpR*Bas)-CCoef[i]);
   End;
   CCoef[0]:=Round(TmpR);
 End;

Procedure SquareFFT(Const ACoef:Array of LongInt; ASize:LongInt; Var CCoef:Array of LongInt);
 Var a, b :Array[0..MaxSize] of complex;
     lst :Array[0..pred(MaxSize)] of Word;
     w   :Array[0..MaxSize shr 1] of complex;
     n, i :LongInt;
     logn :Byte;
     TmpR, num{,maxr,maxi }:Extended;
 Begin
   n:=1;
   logn:=0;
   while n<(aSize+aSize) do Begin n:=n shl 1; Inc(logn); End;
   Initial(w,lst,n);
   for i:=0 to Pred(ASize) do Begin
     a[i].r:=ACoef[i];
     a[i].i:=0;
   End;
   for i:=asize to n do Begin
     a[i].r:=0;  a[i].i:=0;
   End;
{   maxr:=0;
   maxi:=0;}
   FFT(a, b, w, lst, n);
   For i:=0 to pred(n) do Begin
     a[i].r:=b[i].r*b[i].r - b[i].i*b[i].i;
     a[i].i:=b[i].r*b[i].i + b[i].i*b[i].r;
   End;
   invFFT(a, b, w, lst, n);
{   For i:=0 to pred(n) do if Abs(b[i].r)>Maxr then maxr:=Abs(b[i].r);
   For i:=0 to pred(n) do if Abs(b[i].i)>Maxi then maxi:=Abs(b[i].i);}
   TmpR:=0;
   For i:=Pred(n) downto 1 do Begin
     num :=b[Pred(i)].r+TmpR;
     TmpR:=Int((num+0.001)*invBas);
     CCoef[i]:=Round(num-TmpR*Bas);
     If ABS(num-TmpR*Bas-CCoef[i]) > WorstEr Then WorstEr:=Abs((num-TmpR*Bas)-CCoef[i]);
   End;
   CCoef[0]:=Round(TmpR);
 End;

Begin
  Assign(output,'D:/Mulout.txt');
  Rewrite(output);
  Randomize;
  WorstEr:=0;
  fillchar(ACoef,sizeof(ACoef),0);
  fillchar(BCoef,sizeof(BCoef),0);
  asize:=Maxsize shr 1;
  BSize:=Maxsize shr 1;
  For i:=0 to pred(Asize) do
    ACoef[i]:={Round(Bas-1)}Trunc(random*Bas);
  Print(ACoef, Asize); Writeln; writeln('*');
  For i:=0 to pred(Bsize) do
    BCoef[i]:={Round(Bas-1)}Trunc(random*Bas);
  Print(BCoef, BSize); Writeln; Writeln('=');

 Gettime(th1,tm1,ts1,tms1);
   SquareFFT(ACoef,ASize,CCoef);{MulFFT(ACoef, ASize, BCoef, BSize, CCoef);}
 Gettime(th2,tm2,ts2,tms2);

  Print(CCoef, Asize+BSize); Writeln;
  Writeln('Worst Error is ',WorstEr);
  time1:=60*(tm2-tm1)+ts2-ts1;
  If tms2<tms1 then Begin time2:=100+tms2-tms1; Dec(time1); End
                    else time2:=tms2-tms1;
  Writeln('Used ',time1:4,'.',time2:2,'  second');
  Close(output);
End.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

第一次作业 1、 利用循环嵌套完成下列各题: 1、求出100以内的素数。 2、打印形状为正方形和直角三角形(上三角和下三角)的乘法九九表。 3、将一笔零钱(大于8分,小于1元,精确到分)换算成1分、2分和5分的硬币组合。输入金额,输出共有多少种换法及换算的方案。 4、百马百担问题。有100匹马,驮100担货,大马驮3担,中马驮2担,两匹小马驮1担。编写程序求需大、中、小马各多少匹。 5、输入一个正整数,质因数... 阅读详情

相关推荐

【基本算法快速幂和快速乘法详解

文章目录一.快速幂1.简介2.思想3.代码二.快速乘法1.简介2.思想3.代码三.快速幂+快速乘法 快速幂和快速乘法都是利用了二进制的思想,时间复杂度为O(logN)O(logN)O(logN)级别的算法算法有两大优点:①便于取模操作(避免溢出) ②时间复杂度较低 一.快速幂 1.简介 先来说说运用较广的快速算法,虽然math库中有pow函数,但是因为精度问题使用的不是很多,所以在涉及取模时广泛应用的是快速幂的模板 2.思想 以132713^{27}1327为例进行计算 朴素的实现幂次的算法是连乘,即

Qiuker_jl的博客 5722

c语言2位数逆序乘积

两位数逆序乘积,找出AB*CD=BA*DC,例如12*63=21*36

大数乘法快速傅立叶变换)下

大数乘法快速傅立叶变换)下

大田二十 1万+

Python解题-逆序乘积

题目 【问题描述】 若两个正整数的乘积,等于两正整数各自逆序后的乘积,则称其为逆序乘积。编写程序读入两个正整数,然后判断这两个正整数能否构成逆序乘积。假设两个正整数的乘积不会超过int数据类型的表示范围。 【输入形】 从控制台输入以一个空格分隔的两个正整数。 【输出形】 若两个正整数能够构成逆序乘积,则输出两个正整数及其逆序乘积,并且中间用一个等号相连;若不能构成逆序乘积,则输出...

qq_44616044的博客 1472

全国信息水平第六届C语言设计竞赛复赛A卷答案

/* 有一个数学等AB*CD=BA*DC中的一个字母代表一 位数字,试找出所有符合上述要求的乘积并打印输出。 */ #include #include int main() { int A, B, C, D; for (A = 1; A <= 9; A++) { for (B = 1; B <= 9; B++) {

标哥 2269

ITAT复赛答案集锦(1)

第一届 1. 输入一个五位整数,将它反向输出。例如输入12345,输出应为54321。(15分) Strrev(); 2.用两种循环结构分别编程计算1+2+3…+100的值。 运行结果为“1+2+…+100=5050”(15分) 3. 从终端读入20个数据到数组中,统计其中正数的个数,并计算它们之和。(15分) 4. 利用指针实现...

weixin_30677475的博客 387

快速乘法 详解

快速乘法(也称为快速幂的乘法扩展”)是一种用于高效计算两个数乘积算法,特别适合处理大数或在某些特定环境(如计算机低层次硬件实现)中优化乘法运算。其核心思想是将乘法分解为一系列加法和位移操作,从而减少计算复杂度。和分治思想,将乘法运算转化为一系列位移操作和加法。快速乘法广泛用于高效算法中,是程序设计和算法优化的重要工具之一。它们的核心思想都是通过分治和二进制展开优化运算。在某些场景下(如计算大数模运算),需要快速计算。通过快速乘法避免溢出。的二进制位,计算乘积

T_Y_F_的博客 1770

快速乘法 原理详解

快速乘法是通过二进制分解和位操作优化乘法运算的高效算法。它利用二进制的逐位处理特性,大幅减少了计算量,尤其适用于整数运算和大数场景。以下是快速乘法的详细原理解析。快速乘法只使用常数个变量。快速乘法通过处理被乘数。因此,可以通过逐位检查。

T_Y_F_的博客 1527

数论-快速乘法快速

数论-快速乘法快速快速乘法 快速乘法的时间复杂度为O(logn),相比于普通乘法而言确实增加了时间复杂度,所以快速乘法并不快。快速乘法是解决ab%p时ab的结果超出long long 的数据范围的一种方法。 原理 设b的二进制为b₈b₇b₆b₅ b₄b₃b₂b₁。ab%p=a(1b₁+2b₂+4b₃+8b₄+…+128b₈)%p=a1b₁%p+a2b₂%p+…+a128b₈%p。设a_1=a...

ACM_Algorithm 454

快速乘法模板

快速乘法使用二进制将乘法转化为加法,既加快可以加快运算速度,又可以防止直接相乘之后溢出 简单的写法: ll quickMul(ll a,ll b,ll mod) { ll res=0; while(b){ if(b&amp;1) res=(res+a)%mod; a=(a+a)%mod; b&gt;&gt;=1; } ...

紫芝的博客 2878

快速乘法(基于快速幂)

快速乘法的思想和快速幂的思想一样,快速幂是求一个数的高次幂,快速乘法是求两个数相乘,什么时候才用得到快速乘法呢,当两个数相称可能超过long long 范围的时候用,因为在加法运算的时候不会超,而且可以直接取模,这样就会保证数据超不了了。具体拿一个BestCoder的题目来示例。题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5187 这个...

dizhuo0219的博客 226

快速幂&快速乘法

尽管快速幂与快速乘法好像扯不上什么关系,但是东西不是很多,就一起整理到这里吧 快速幂思想就是将ax看作x个a相乘,用now记录当前答案,然后将指数每次除以2,然后将当前答案平方,如果x的2进制最后一位为1的话,就将答案乘以现在的数。快速乘法类似,只是将a*x看作x个a相加。 代码    1 #include<cstdio> 2 #include<i...

diecimu4798的博客 122

快速矩阵乘法的研究——上

快速矩阵乘法的研究 最近的工作主要在于深度学习框架的性能优化。深度学习框架在工程的优化(内存池、SIMD、汇编、GPU、DSP等等)做到接近极限之后,突破点便集中于算法。 深度学习的性能瓶颈主要在于卷积,卷积的运算方法主要是通过 Im2Col / Winograd / FFT 转化为矩阵乘,完成矩阵乘法之后,再转化为目标结果。 深度学习框架的输入是算法工程产出的网络模型,而目前网络模型都渐渐地转变...

jxt1234and2010的专栏 4754

【数论】【模板】快速幂、快速乘法以及矩阵乘法、矩阵快速

普通快速幂: ll quick_mod(ll a,int n) { ll sum=1;//注意是乘法,所以初始化为1 while(n) { if(n&1)//&运算符表示取这个数二进制的最后一位 { sum=sum*a%mod;//若这位为1那么总和就应该乘当前的a } ...

追风者 384

快速幂和快速乘法

快速幂和快速乘法的原理类似。 都是巧妙使用二进制的算法。 代码如下: #include&lt;iostream&gt; #include&lt;cstdio&gt; #include&lt;algorithm&gt; #include&lt;cstring&gt; using namespace std; int poww(int a,int b) { int ans=1,base=a; ...

chunxiao12345的博客 285

快速乘法/幂 算法详解

快速乘法 快速算法详解 数论,位运算 适用范围:快速计算a*b % mod的结果,或者快速计算a^b % mod 的结果,时间复杂度大大降低。 算法描述:首先你可能会问a*b不是直接乘就出来了么,为什么需要快速算法?但是乘法在计算机中处理的时间并不是这么快的,也要拆分为加法来做的。所以快速乘法会更快的计算a*b的结果。

JUST CODE 1万+

快速乘法快速幂法

快速乘法快速幂法 1、快速乘法 基本原理: 利用乘法的分配率。定义a=a1+a2+a3+…,则a*b = (a1+a2+a3+…)*b。 使用快速乘法计算X*53。53的二进制表示是 110101,根据乘法分配率X*53可以表示成X*(100000*1+10000*1+1000*0+100*1+10*0+1*1)。假设X=5,可以使用下面的流转图表示。 可以看出 a 的状态方程为 a+=a,b的状态方程为 b>>&1,ans 的状态方程为 ans+=a。因此可以得到一下代码 代码:

System_out_println6的博客 437
下一篇: 名言名句
yenit
博客等级 码龄21年 0粉丝 13原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值