分治法(逆序数 大数乘法)

2024-04-28 16:32
文章标签 大数 分治 乘法 序数

本文主要是介绍分治法(逆序数 大数乘法),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

例子:

An old puzzle: We are given 27 coins of the same denomination; we know that one of them is counterfeit and that it is lighter than the others. Find the counterfeit coin by weighing coins on a pan balance only three times.Solution:This method is called "divide-and-conquer"We have already seen a prototypical "serious" algorithm designed using such a method: the merge sortwe split the array into two,sort the two parts recursively and then merge the two sorted arrays.

设计思路:

对于一个规模为n的问题 若该问题可以容易的解决则直接解决
否则将其分解成k个规模较小的子问题
这些子问题互相独立 且与 原问题形式相同
递归地解决这些子问题
然后将各子问题的解合并得到原问题的解

使用情况

	该问题的规模缩小到一定的程度就可以很容易的解决该问题可以分解为若干个规模较小的相同问题 即该问题具有最优子结构性质利用该问题分解出的子问题的解可以合并为该问题的解该问题所分解出的各个子问题是相互独立的即子问题之间不包含公共的子子问题

基本步骤

1.分解:分解成若干规模小 相互独立 与原问题形式相同的子问题
2.解决:直接解决或者递归求解
3.合并:合并各子问题的解来得到原问题的解

例子

计算逆序对
逆序对: if i < j && a[i] > a[j]  就是一个逆序对arr: 1 11 9 12 7 10 3 4 6 8 2 5brute force: O(n^2)
divide&conquer: 
步骤:1.分解先进行对半划分 直到最后左半边数组只有一个元素 右半边数组中也只有一个元素 此时开始进行回溯合并。2.合并在回溯过程中 左半边和右半边元素都是升序排列 当发现左边元素大于右边元素时,那么左半边这个元素及其后面的所有元素均大于这个右半边的元素 记这些元素的个数为len 那么逆序对的个数要自增 mid - left + 13. 代码(merge sort + count)import java.util.Arrays;public class DivideAndConquer {public  static int conquer(int []nums,int left,int mid,int right) {int[] tmp = new int[right-left+1];int i = 0;int l = left;int m = mid+1;int count = 0;while( l <= mid && m <= right ) {if( nums[l] < nums[m] ) {tmp[i++] = nums[l++];}else {tmp[i++] = nums[m++];count += mid - l + 1;}}while( l <= mid ) {tmp[i++] = nums[l++];}while( m <= right ) {tmp[i++] = nums[m++];}for(int s = 0; s <= (right-left) ;s++) {nums[left+s] = tmp[s];}return count;}public static int divide(int[] nums,int left,int right) {int mid = (left+right)/2;int count = 0;if(left < right) {count += divide(nums, left, mid);count += divide(nums, mid+1, right);count += conquer(nums,left,mid,right);System.out.println( Arrays.toString(nums)+" "+count );}return count;
}public static void main(String[] args) {int[] nums = {10,2,0,12,5,3};divide(nums, 0, nums.length-1);}
}

分治法的时间复杂度:

假设:有一个规模为n的问题 时间函数为T(n)分成k个问题 每个问题的规模为n/m, 则每个子问题的时间函数为T(n/m)最小子问题为n=1,解规模为1的问题时需耗费1个单位时间。将子问题的解合并为原问题的解需要f(n)=n的d次方 个时间单位O(1)    n = 1T(n)= {K*T(n/m) + f(n) n>1

大数乘法

先看看大数加法:int、float、double等基本数据类型的数据容量有限,不深究它们的具体范围是多大,但粗略估算,大概也不超过25位吧。如果有一个是50位的数字,基本数据类型根本无法存储这么大的数字,那我们应该怎么办?这时候,我们应该采用大数的思想:用数组来分别保存这50位数字中各个位的数字。大数加法的时间复杂度是 O(n) n位数对应相加
大数乘法是进行n次 加法运算 所以时间复杂度是 O(n^2)
用分治法进行优化:分治法的算法是A*B=a1*b1*10^n+[(a1+a0)*(b0+b1)-a1*a0-b1*b0]*10^n/2+a0*b0对于这个算法的时间复杂度,我们需要做3次n/2级别的乘法。即T(n)=3*T(n/2)+O(n),时间复杂度是T(n) = O(n^log2(3) ) = O(n^1.59 ).
我们假设要相乘的两个数是x * y。我们可以把x,y写成:x=a∗10n/2+by=c∗10n/2+dA * B = c2 * 10^n + c1 * 10^(n/2) + c0其中:c2 = a1 * b1c1 = a0 * b1 + b0 * a1 = (a1 + a0) * (b1 + b0) - (c2 + c0)

这篇关于分治法(逆序数 大数乘法)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/943720

相关文章

uva 10069 DP + 大数加法

代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#include <stack>#include <vector>#include <queue>#include <map>#include <cl

Codeforces Round #240 (Div. 2) E分治算法探究1

Codeforces Round #240 (Div. 2) E  http://codeforces.com/contest/415/problem/E 2^n个数,每次操作将其分成2^q份,对于每一份内部的数进行翻转(逆序),每次操作完后输出操作后新序列的逆序对数。 图一:  划分子问题。 图二: 分而治之,=>  合并 。 图三: 回溯:

hdu 6198 dfs枚举找规律+矩阵乘法

number number number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Problem Description We define a sequence  F : ⋅   F0=0,F1=1 ; ⋅   Fn=Fn

Java验证辛钦大数定理

本实验通过程序模拟采集大量的样本数据来验证辛钦大数定理。   实验环境: 本实验采用Java语言编程,开发环境为Eclipse,图像生成使用JFreeChart类。   一,验证辛钦大数定理 由辛钦大数定理描述为: 辛钦大数定理(弱大数定理)  设随机变量序列 X1, X2, … 相互独立,服从同一分布,具有数学期望E(Xi) = μ, i = 1, 2, …, 则对于任意正数ε ,

【SGU】180. Inversions(归并排序求逆序数)

以前一般用树状数组和线段树做这种题 这次换个思路试试,归并排序! #include<cstdio>#include<cstring>#include<algorithm>using namespace std;typedef long long LL;const int maxn = 111111;int n;int array[maxn];int tmp[maxn];L

高精度加法,乘法,阶乘

#include <iostream>#include <map>#include <string>#include <algorithm>using namespace std;const int Max = 50000;string str1,str2;/***********乘法***********/void chenfa(){cin >> str1>>str2;int a

找第K大数(ACdream 1099)

瑶瑶的第K大 Time Limit: 4000/2000MS (Java/Others)  Memory Limit: 256000/128000KB (Java/Others) Submit  Statistic  Next Problem Problem Description 一天,萌萌的妹子--瑶瑶(tsyao)很无聊,就来找你玩。可是你们都不知道玩什么。。。

乘法问题c++

题目描述 小 A 最近刚刚学习了乘法,为了帮助他练习,我们给他若干个正整数,并要求他将这些数乘起来。 对于大部分题目,小 A 可以精准地算出答案,不过,如果这些数的乘积超过 ,小 A 就不会做了。 请你写一个程序,告诉我们小 A 会如何作答。 输入 第一行一个整数 n,表示正整数的个数。 接下来 n行,每行一个整数a 。小 A 需要将所有的 a乘起来。 保证n<=50,a<=100. 输出

分治算法与凸包问题

1. 什么是凸包问题? 凸包问题是计算几何中的经典问题。给定二维平面上的点集,凸包是一个最小的凸多边形,它包含了点集中所有的点。你可以把凸包想象成一根松紧带将所有点紧紧包裹住的样子,凸包的边缘仅沿着最外面的点延伸。 2. 分治法简介 分治算法是解决复杂问题的强大策略,它的思想是将问题分解为多个子问题,分别解决这些子问题后再合并得到最终解。凸包问题可以通过分治算法高效地解决,时间复杂度可以达到