分治法的经典问题——大整数相乘

分治法的经典问题——大整数相乘

分治法的原理

       分治算法的基本思想是将一个规模为N的问题分解为K个规模较小的子问题,这些子问题相互独立且与原问题性质相同。求出子问题的解,就可得到原问题的解。即一种分目标完成程序算法,简单问题可用二分法完成。(来自度娘的搬运工)

       简单的说,分治就是分而治之,把一个问题拆分成几个小问题,最后再汇总解决的办法。

有两点需要记住:

(1) 分治法基本思想是将一个规模为n的问题分解为k个规模较小的子问题,这些子问题相互独立且与原问题相同。

(2)递归的解这些子问题,然后将各子问题的解合并得到原问题的解。

分治法的重点是分析问题是否可以划分为规模较小的子问题,难点是如何划分以及划分之后如何将各个子问题的解合并成最终的解。这一般需要用到数学知识或者其他理论。

下面我们用图来说明:

 

 

通过大整数相乘问题来了解分治法(理想状态下)

       这里我们假设有两个大整数X、Y,分别设X=1234、Y=5678。现在要求X*Y的乘积,小学的算法就是把X与Y中的每一项去乘,但是这样的乘法所需的时间复杂度为,效率比较低下。那我们可以采用分治的算法,将X、Y分别拆分为A与B、C与D,如下图:

 

 

 

注:我们这里取的大整数X、Y是在理想状态下,即X与Y的位数一致,且

 

 

算法分析

  1. 首先将X和Y分成A,B,C,D
  2. 此时将X和Y的乘积转化为(1)式,把问题转化为求解因式分解的值

在(1)式中,我们一共需要进行4次n/2的乘法(AC2次,AD、BC各一次)和3次加法,因而该算法的时间复杂度为:

 

通过master定理可以求得,跟小学算法的时间复杂度没有区别。

但是我们再来看看,我们是否可以用加法来换取乘法?因为多一个加法操作,也是常数项,对时间复杂度没有影响,如果减少一个乘法则不同。

(1)式化为:

 (2)

现在的时间复杂度为:,通过master定理求得,

理想状态下代码实现(部分):

c#:

static void Main(string[] args)
        {
            //SameNumber();
            //UnSameNumber();
            UnSameNumber2();
        }

        static int SIGN(long A)
        {
            return A > 0 ? 1 : -1;
        }

        #region 两整数位数相同
        private static void SameNumber()
        {
            Console.Write("请输入两个大整数:\nX=");
            long X = Convert.ToInt64(Console.ReadLine());
            Console.Write("Y=");
            long Y = Convert.ToInt64(Console.ReadLine());
            Console.Write("请输入两个大整数的长度:n=");
            int n = Convert.ToInt32(Console.ReadLine());

            long sum = CalculateSame(X, Y, n);

            Console.WriteLine("普通乘法 X*Y={0}*{1}={2}\n", X, Y, X * Y);
            Console.WriteLine("分治乘法 X*Y={0}*{1}={2}\n", X, Y, sum);
        }

        static long CalculateSame(long X, long Y, int n)
        {
            int sign = SIGN(X) * SIGN(Y);

            X = Math.Abs(X);
            Y = Math.Abs(Y);
            if (X == 0 || Y == 0)
                return 0;
            else if (n == 1)
                return sign * X * Y;
            else
            {
                long A = (long)(X / Math.Pow(10, n / 2));
                long B = (long)(X % Math.Pow(10, n / 2));
                long C = (long)(Y / Math.Pow(10, n / 2));
                long D = (long)(Y % Math.Pow(10, n / 2));

                long AC = CalculateSame(A, C, n / 2);
                long BD = CalculateSame(B, D, n / 2);
                long ABCD = CalculateSame((A - B), (D - C), n / 2) + AC + BD;

                //Console.WriteLine("A={0} B={1} C={2} D={3}\n", A, B, C, D);

                return (long)(sign * (AC * Math.Pow(10, n) + ABCD * Math.Pow(10, n / 2) + BD));
            }
        }
        #endregion

 

 

大整数相乘算法非理想状态下

       这里我们还是假设有两个大整数X、Y,分别设X=123、Y=45678。现在要求X*Y的乘积,乘法所需的时间复杂度为。我们采用分治的算法,将X、Y分别拆分为A与B、C与D,如下图:

 

        (3)

在(3)式中,我们一共需要进行2次xn0的乘法(AC、AD各一次)、2次yn0的乘法(AC、BC各一次)和3次加法,因而该算法的时间复杂度为:

 </

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值