大整数乘法(分治法)

大整数乘法(分治法)
大整数乘法(分治法)

#include

#include

#include

#include

#define DATASIZE 1000

//该函数用以接收用户输入的大整数,返回值为该大整数的数字位数

int InputBigInt(int arr[])

{

char ch;

int i=0;

printf("Input a Big Interger:");

while(1)

{

scanf("%c",&ch);

if(ch=='\n') break;

else arr[i++]=ch-'0';

}

return i;

}

//该函数通过在较短的大整数之前填充0的方式,将两个大整数的位数对齐,返回值为较长的那个大整数的位置

int AlignArray(int *a,int len_a,int *b,int len_b)

{

int len_align=len_a;

if(len_a>len_b)

{

for(int i=len_b-1;i>=0;i--)

b[i+(len_a-len_b)]=b[i];

for(int i=0;i

b[i]=0;

len_align=len_a;

}

else if(len_a

{

for(int i=len_a-1;i>=0;i--)

a[i+(len_b-len_a)]=a[i];

for(int i=0;i

a[i]=0;

len_align=len_b;

}

return len_align;

}

//该函数通过删去大整数前面无意义的0来得到其真实的数字位数

int Adjust(int a[],int len)

{

while(a[0]==0)

{

int j=1;

do{

a[j-1]=a[j];

j++;

}while(j

len--;

}

return len;

}

//两个长度为length的大整数做加法,得到的结果放到数组C中,长度为length+1 int Add(int a[],int b[],int c[],int length)

{

int carry=0;

for(int i=length-1;i>=0;i--)

{

int t=a[i]+b[i]+carry;

c[i+1]=t%10;

carry=t/10;

}

c[0]=carry;

return length+1;

}

//两个长度为length的大整数做减法,得到的结果放到数组C中,长度为length int Sub(int a[],int b[],int c[],int length)

{

int borrow=0;

for(int i=length-1;i>=0;i--)

{

a[i]=a[i]-borrow;

if(a[i]>=b[i])

{

c[i]=a[i]-b[i];

borrow=0;

}

else

{

int t=a[i]+10-b[i];

borrow=1;

}

}

return length;

}

//分治法求两个大整数的乘积,它只需要更少次数的乘法,但是它必须递归int DividBigIntMultiply(int a[],int b[],int c[],int len)

{

int l=len/2;

if(len==1)

{

int t=a[0]*b[0];

c[0]=t/10;

c[1]=t%10;

return 2;

}

else if(len==2)

{

int t1=a[1]*b[1];

c[3]=t1%10;

int t2=a[0]*b[1]+a[1]*b[0]+t1/10;

c[2]=t2%10;

int t3=a[0]*b[0]+t2/10;

c[1]=t3%10;

c[0]=t3/10;

return 4;

}

else

{

int *a1,*a0,*b1,*b0;

a1=(int *)malloc(l*sizeof(int));

a0=(int *)malloc((len-l)*sizeof(int));

b1=(int *)malloc(l*sizeof(int));

b0=(int *)malloc((len-l)*sizeof(int));

if(a1==NULL || a0==NULL || b1==NULL || b0==NULL)

{

printf("内存分配失败,递归失败,程序退出!\n");

exit(0);

}

//将原来的两个大整数,分治为一半,分别放入到a1,a0和b1,b0四个数组当中去for(int i=0;i

{a1[i]=a[i];b1[i]=b[i];}

for(int i=l;i

{a0[i-l]=a[i];b0[i-l]=b[i];}

int l1=AlignArray(a1,l,a0,len-l);

int l2=AlignArray(b1,l,b0,len-l);

l=l1;

//先求得c2和c0,直接做乘法就可以了

int *c2,*c0;

c2=(int *)malloc(2*l*sizeof(int));

c0=(int *)malloc(2*l*sizeof(int));

if(c2==NULL || c0==NULL)

{

printf("内存分配失败,递归失败,程序退出!\n");

exit(0);

}

DividBigIntMultiply(a1,b1,c2,l); //c2=a1*b1,长度为2*l

DividBigIntMultiply(a0,b0,c0,l); //c0=a0*b0,长度为2*l

//再来求得c1,这里有乘法也有加法,还有减法

//c1=(a1+a0)*(b1+b0)-(c2+c0)

int *t1,*t2,*t3,*t4,*c1;

t1=(int *)malloc((1+l)*sizeof(int)); //t1=a1+a0

t2=(int *)malloc((1+l)*sizeof(int)); //t2=b1+b0

t3=(int *)malloc((1+2*l)*sizeof(int)); //t3=t1*t2

t4=(int *)malloc(2*(l+1)*sizeof(int)); //t4=c2+c0

c1=(int *)malloc(2*(l+1)*sizeof(int)); //c1=t3-t4

if(t1==NULL || t2==NULL || t3==NULL)

{

printf("内存分配失败,递归失败,程序退出!\n");

exit(0);

}

int len1=Add(a1,a0,t1,l); //t1=a1+a0,长度为l+1

int len2=Add(b1,b0,t2,l); //t2=b1+b0,长度为l+1

int len4=Add(c2,c0,t4,2*l); //t4=c2+c0,长度为2*l+1

int len3=AlignArray(t1,len1,t2,len2);

DividBigIntMultiply(t1,t2,t3,len3); //t3=t1*t2,长度为2*(l+1)

int k=AlignArray(t4,len4,t3,len3); //将c1与t3对齐,长度为2*(l+1)int len5=Sub(t4,t3,c1,k); //c1=t4-t3,长度为2*(l+1)

//打印输出c2,c1和c0

int i=0;

printf("c2=");

while(c2[i]==0) i++;

for(;i<2*l;i++)

printf("%d",c2[i]);

printf("\n");

int j=0;

printf("c0=");

while(c0[j]==0) j++;

for(;j<2*l;j++)

printf("%d",c0[j]);

printf("\n");

int n=0;

printf("c1=");

while(c1[n]==0) n++;

for(;n

printf("%d",c1[n]);

printf("\n");

}

return 2*len;

}

void main()

{

int a[DATASIZE],b[DATASIZE],c[2*DATASIZE];

int len_a,len_b,len_align;

len_a=InputBigInt(a); //输入大整数a

len_b=InputBigInt(b); //输入大整数b

len_align=AlignArray(a,len_a,b,len_b); //针对两个大整数做对齐int l=DividBigIntMultiply(a,b,c,len_align);

int i=0;

while(c[i]==0) i++;

for(;i

printf("%d",c[i]);

printf("\n");

}

0007算法笔记——【分治法】最接近点对问题

问题场景:在应用中,常用诸如点、圆等简单的几何对象代表现实世界中的实体。在涉及这些几何对象的问题中,常需要了解其邻域中其他几何对象的信息。例如,在空中交通控制问题中,若将飞机作为空间中移动的一个点来看待,则具有最大碰撞危险的2架飞机,就是这个空间中最接近的一对点。这类问题是计算几何学中研究的基本问题之一。 问题描述:给定平面上n个点,找其中的一对点,使得在n个点的所有点对中,该点对的距离最小。严格地说,最接近点对可能多于1对。为了简单起见,这里只限于找其中的一对。 1、一维最接近点对问题 算法思路: 这个问题很容易理解,似乎也不难解决。我们只要将每一点与其他n-1个点的距离算出,找出达到最小距离的两个点即可。然而,这样做效率太低,需要O(n^2)的计算时间。在问题的计算复杂性中我们可以看到,该问题的计算时间下界为Ω(nlogn)。这个下界引导我们去找问题的一个θ(nlogn)算法。采用分治法思想,考虑将所给的n个点的集合S分成2个子集S1和S2,每个子集中约有n/2个点,然后在每个子集中递归地求其最接近的点对。在这里,一个关键的问题是如何实现分治法中的合并步骤,即由S1和S2的最接近点对,如何求得原集合S中的最接近点对,因为S1和S2的最接近点对未必就是S 的最接近点对。如果组成S的最接近点对的2个点都在S1中或都在S2中,则问题很容易解决。但是,如果这2个点分别在S1和S2中,则对于S1中任一点p,S2中最多只有n/2个点与它构成最接近点对的候选者,仍需做n^2/4次计算和比较才能确定S的最接近点对。因此,依此思路,合并步骤耗时为O(n^2)。整个算法所需计算时间T(n)应满足:T(n)=2T(n/2)+O(n^2)。它的解为T(n)=O(n^2),即与合并步骤的耗时同阶,这不比用穷举的方法好。从解递归方程的套用公式法,我们看到问题出在合并步骤耗时太多。这启发我们把注意力放在合并步骤上。 设S中的n个点为x轴上的n个实数x1,x2,..,xn。最接近点对即为这n个实数中相差最小的2个实数。我们显然可以先将x1,x2,..,xn排好序,然后,用一次线性扫描就可以找出最接近点对。这种方法主要计算时间花在排序上,在排序算法已经证明,时间复杂度为O(nlogn)。然而这种方法无法直接推广到二维的情形。因此,对这种一维的简单情形,我们还是尝试用分治法来求解,并希望能推广到二维的情形。假设我们用x轴上某个点m将S划分为2个子集S1和S2,使得S1={x∈S|x≤m};S2={x∈S|x>m}。这样一来,对于所有p∈S1和q∈S2有p

C语言两个大整数相乘

两个极大整数相乘 主要的思路是将数字当作字符串逆序读入字符串a, b中,数据结构如表中所示: 下面是源码: /*“两个极大整数相乘.cpp”*/ /*本方法采用数组逆序存储大整数,首位存数字长度,更方便操作,希望能给予大家一些启发*/ #include #include #define MAX 4096 //理论最大可计算位数: min(m,n)=26512143 void myread(int*a); //读函数,将数字逆序读取,并存在数组中 void myprint(int *a); //用于打印最后结果(包含正序和去除首位的0) double plus(); //用于两个长整数的加法 void add(); //考虑进位问题,将数组每一单元的数转化为个位数 int a[MAX],b[MAX],t[MAX]; int main() { printf("大整数之间的乘法运算。\n"); printf("请输入第一个整数:\n"); myread(a); printf("请输入第二个整数:\n"); myread(b); // printf("中间数最大数为:%.0lf\n",plus()); //测试最大中间值 // for(int i=1;i<=t[0];i++) // printf("t[%d]=%d\n",i,t[i]); //测试每一个数层的数 add(); printf("结果是:"); myprint(t); return 0; } void myread(int *a) { char s[MAX]; scanf("%s",s); a[0]=strlen(s); for(int i=a[0];i>=1;i--) a[i]=s[a[0]-i]-'0'; }

大整数乘法(分治法)

#include #include #include #include #define DATASIZE 1000 //该函数用以接收用户输入的大整数,返回值为该大整数的数字位数 int InputBigInt(int arr[]) { char ch; int i=0; printf("Input a Big Interger:"); while(1) { scanf("%c",&ch); if(ch=='\n') break; else arr[i++]=ch-'0'; } return i; } //该函数通过在较短的大整数之前填充0的方式,将两个大整数的位数对齐,返回值为较长的那个大整数的位置 int AlignArray(int *a,int len_a,int *b,int len_b) { int len_align=len_a; if(len_a>len_b) { for(int i=len_b-1;i>=0;i--) b[i+(len_a-len_b)]=b[i]; for(int i=0;i=0;i--) a[i+(len_b-len_a)]=a[i]; for(int i=0;i

a[i]=0; len_align=len_b; } return len_align; } //该函数通过删去大整数前面无意义的0来得到其真实的数字位数 int Adjust(int a[],int len) { while(a[0]==0) { int j=1; do{ a[j-1]=a[j]; j++; }while(j=0;i--) { int t=a[i]+b[i]+carry; c[i+1]=t%10; carry=t/10; } c[0]=carry; return length+1; } //两个长度为length的大整数做减法,得到的结果放到数组C中,长度为length int Sub(int a[],int b[],int c[],int length) { int borrow=0; for(int i=length-1;i>=0;i--) {

大整数乘法--C++

大整数乘法 仅供参考 #include #include using namespace std; void MUL_max(string a,int la,string b,int lb,int **c);//相乘函数 void ADD_max(int * d,int **c,int la,int lb);//相加函数 char * ZhuanH(string); void main() { string a; string b; int **c=NULL; int *d=NULL; int la=0,lb=0; int i=0,j=0,k=0; cout<<" ************大整数乘法**************"<>a; cout<<"请输入被乘数:"; cin>>b; la=a.length(); lb=b.length(); //分配2维C数组,存储数组a和b的乘积 c=new int*[la]; for(k=0;k

d[i]=0; //初始化数组C,便于后面判断相加后的有效位数for(i=0;i

大整数乘法问题

大整数乘法问题 一、问题分析 (1)采用分治法的思想,将一个多位的二进制数分成几个位数较少的二进制数进行计算。这样不断地往下分,直到分出的二进制数相对简单,可以直接算出来。 (2)对于这个算法,上课时讲过了时间复杂度为O(n^1.59)。 二、问题解决 (1)具体程序代码(c++) #include #include using namespace std; #define M 100 #define N 100 ifstream infile; ofstream outfile; int Weishu(int u[]); int *add(int *m,int *n); int *Mul(int n,int *u,int *v); int Weishu(int u[]) { int t=0; while(u[t]==1 || u[t]==0){ t++; } return t; } int *Mul(int n,int *u,int *v) { int w[M],x[M],y[M],z[M];

int a[M],b[M],c[M],d[M]; int wy[M],xz[M],wz[M],xy[M]; int *aa,*bb,*cc,*dd; int mid; int i,j; int Ji[M],k=0; if(n==1) { Ji[k]=u[0]*v[0]; k++; return(Ji); } else { mid=(n+1)/2; for(i=0;i

大整数的乘法实验报告

算法设计与分析实验报告 姓名:XXX 班级:XXX 学号:XXX

一、实验名称:大整数的乘法 时间:2012年3月7日,星期三,第四节 地点:12#311 二、实验目的及要求 实现大整数相乘,需要处理很大的整数,它无法在计算机硬件能直接表示的整数范围内进行处理。若用浮点数来表示它,则只能近似的表示它的大小,计算结果中的有效数字也受到限制。如要精确地表示大整数并在计算结果中要求精确地得到所有位数上的数字,就必须用软件的方法来实现大整数的算术运算。 三、实验环境 Vc++。 四、实验内容 从键盘上输入两个大整数,实现两个大整数相乘,并输出结果。 例如:在键盘上输入两个数a,b。 a=9876543210; b=369852147; 五、算法描述及实验步骤 定义三个数组a[100],b[100],c[199]。 用数组a来存放大整数a,a[0]=9,a[1]=8,a[2]=7,a[3]=6,a[4]=5,a[5]=4,a[6]=3, a[7]=2,a[8]=1,a[9]=0; 用数组b来存放大整数b,b[0]=3,b[1]=6,b[2]=9,b[3]=8,b[4]=5,b[5]=2,b[6]=1 b[7]=4,b[8]=7。 用数组c来存放数组a和b每一位的乘积, c[0]=a[0]*b[0]; c[1]=a[1]*b[0]+a[0]*b[1]; c[2]=a[2]*b[0]+a[1]*b[1]+a[0]*b[2]; …… …… c[17]=a[9]*b[8]; 六、调试过程及实验结果 void make(int a[],int aa,int b[],int bb,int c[]){ int i,j; for(i=0;i

大数乘法算法

大数乘法算法 实际上也可以拿相似的思想做大数相乘,只是把输入源从链表变为数组即可。 基本原理: 1,把两个数字a和b转换成字符,放到字符数组里;或者把数字的每一位隔离开分别放到数组里作为一位,这样更方便乘法处理。这样做的根本好处是:相乘的时候不会造成溢出。 2,结果数组的长度,最大应该是a的长度+b的长度+1,所以定义一个这样的数组; 3,过程很简单了:a中的第i位乘以b中的第j位,保存在c中的第i+j位; 4,后期处理。注意,经过第三步处理过的c中的结果,每一位都可能向高位进位;比如说,c[8]=24.这时候就要从低位开始把进位部分向高位加,一次循环即可: for(i=0;i10,那么立刻进行进位处理。于是提高之后的版本是: for(i=0;i10.不过他也有他自己的处理:如果系数为0的话,就把该项删除,呵呵。 # include# include# include void multiply(char* a,char* b,char* c) { int i,j,ca,cb,* s;

大整数的四则运算高质量c语言程序

设计题目:大整数的四则运算 1. 功能简介:编写出实现大整数之间相加,相减,相乘,相除的程序,并输出计算结构。 课程设计要求:采用模块化程序设计 源程序中应有足够的注释 必须上机调试通过 注重算法运用,优化存储效率与运算效率 需提交源程序(含有注释)及相关文件(数据或数据库文件); 提交设计报告书。 2.总体结构:

数据初判断运算符 加法 正整数非正整 转变为 减法 转变为 乘法除法 转变为 退出 流程图:

3 .概要设计:

1)加法运算 利用两个整形数组分别存放两个数a和b的每一位的数值,最低位存放符号。如果a 和b同号,从最低为开始计算,如果有进位则保存在高一位,本为则减10,然后反序将计算后的各个位的数值保存在一个数组c并输出,如果a和b都是负数则在前面要输出负号,函数的返回值为c的位数。如果a和b异号,也即两个正整数相减,从最低位开始相减,如果要借位则本位加10再相减,高一位要减1,然后反序将计算后的各个位的数值保存在一个数组c并输出,在前面要输出相应的符号位。 2)减法运算 可将减法运算转化为加法运算,只要将被减数的符号改变即可。 3)乘法运算 符号存放在最低位,将其中一个数a的每一位分别乘以另一个数b的每一位,并将结果保存在数组c中,然后重复计算a的下一位跟b的每一位的乘积,把上一次计算保存在c 的值加上本次计算后的值,并保存在c自身中,直到a的最高位,最后输出符号和相应的计算结果。 4)除法运算 利用乘法和减法,将除数分别乘以1到9,直到其值大于等于被除数的对应的数,然后被除数对应的数减去其乘积,保存在一个数组中,下一次循环把它归到被除数中继续做除法运算,最后得到余数并输出。 4.函数功能: 1.void init(int a[],int b[],int *p1,int *p2) 2.功能说明:读入所要计算的数值,数据初始化 3.i nt plus(int a[],int b[],int c[],int m,int n) 4.功能说明:两个正整数相加 3. void change(int a[],int b[],int m,int n) 功能说明:当两异号数相加时,改变其符号以符合加法运算 5.i nt minus(int a[],int b[],int d[],int m,int n)

分治法

分治法 【摘要】:分治法可以通俗的解释为:把一片领土分解,分解为若干块小部分,然后一块块地占领征服,被分解的可以是不同的政治派别或是其他什么,然后让他们彼此异化。本文主要叙述了分治法的设计思想及与之有关的递归思想,了解使用分治法解决问题的过程。 【关键词】:分治法分解算法递归二分搜索 Partition Method (Junna Wei) 【abstract 】: the partition method can explain to popular: decomposition, put a slice of territory is decomposed into several pieces of small, then pieces of land occupation of conquest, the decomposition can be different political factions or something, then let them each other alienation. This paper mainly describes the design idea of the partition method and recursive thinking, related to understand the process of solving the problem using the partition method. 【key words 】: partition method decomposition algorithm recursive Binary search 1.引论

基于FFT的大整数乘法

基于FFT 的大整数乘法 1背景 对于两个长度为n 的大整数,普通的大整数乘法的时间复杂度是()2n O ,而采用一种精心构造的分治算法,则可以将时间复杂度降低为()()585.13log 2n O n O ≈。此处则是受到快速傅立叶变换算法的启发,提出一种新的大整数乘法,该算法基于模-p 的有限域运算,采用类似于FFT 的算法,可以将大整数乘法的时间复杂度降低为() 5.1n O ,甚至,从某种意义上说,可以达到()n n O log 。 2 基础 2.1 FFT (可以参考《算法导论》及《算法概论》相关内容) 对于两个n-1次多项式 3 基于FFT 的大整数乘法 3.1大整数的表示方法 为简便起见,这里只考虑10进制大整数,但是这样并不会失去其一般性。对于一个10进制整数,可以将其表示为: ()01221110101010a a a a A n n n n +?++?+?=---- 这样,就可以将一个大整数对应到一个n-1次多项式上去: ()012211a x a x a x a x A N n n n n A ++++=---- ,其中{}9,8,7,6,5,4,3,2,1,0∈i a 3.2大整数的乘法 对于两个十进制大整数A N 和B N ,设A N 各个位上的数字如下: 0121a a a a n n -- 而B N 各个位上的数字如下: 0121b b b b n n -- 另外记多项式 ()012211a x a x a x a x A n n n n ++++=---- , ()012211b x b x b x b x B n n n n ++++=---- 于是有()10A N A =,()10B N B =。

java大整数包课程设计、各种运算

import java.util.*; public class BigNum { public static void main(String[] args){ String s,s1=null,s2=null; Scanner cin = new Scanner(System.in); char op; System.out.println("请输入第一个大整数,并按回车结束:"); if(cin.hasNext()) { s1 = cin.next(); } System.out.println("请输入要进行的运算的运算符,并按回车结束:"); s = cin.next(); op = s.charAt(0); System.out.println("请输入第二个大整数,并按回车结束:"); if(cin.hasNext()) { s2 = cin.next(); } if(op=='+') { System.out.println("最终结果为:"); System.out.println(add(s1,s2)); } if(op=='-') { System.out.println("最终结果为:"); System.out.println(jianfa(s1,s2)); } if(op=='*') { System.out.println("最终结果为:"); System.out.println(chengfa(s1,s2)); } if(op=='/') { System.out.println("最终结果为:"); System.out.println(chufa(s1,s2)); } if(op=='%') { System.out.println("最终结果为:"); System.out.println(quyu(s1,s2)); } if(op=='M') { String s3 = null;

两个n位大整数相乘算法

求最大元和次大元 1.问题描述 从多个数中一次性查找出元素最大的值和最小值,查找元素规模即元素的个数n,用分治的思想编制程序,实现分治的最大元和最小元求法。进一步改进算法,使之能一次性求出最大和和次大元(即第二大元素)。 2.算法设计思想及描述 分治发的基本思想是将一个规模为n 的问题分解为k 个规模较小的子问题,这些子问题相互独立与原问题相同。递归地解决这些问题,然后将各个子问题的解合并得到原问题的解。基于课堂的分析知道,对于本问题k 的值取为2,这样可以使子问题的规模是相同的,有利于算法实现。 为平衡分治时子问题的规模,这里约定需要查找元素的规模n 是2的幂次方。 用数组存储需要查找的元素,用结构体存储返回的最大元和最小元。每次得到局部的最大元和局部次大元,然后局部最大元和最大元比较得到新的局部最大元,次大元和次大元比较得到新的局部次大元。深入分析,这种方式局部次大元是错误的。如两组元素中,a1>b1,a2>b2,当然a1和a2中较大的是新的局部最大元,但是b1和b2中较大的元素不是这四个元素中第二大的。 这样的方法漏掉了b1可能是次大元的情况,也就是说所有的元素中的次大元可能在与最大元比较的时候被漏掉了。弥补的方法就是每次将每个元素比自身小的元素都用一个淘汰数组保存起来,最后次大元就是最大元的淘汰数组中第二大的那个元素。 3.算法分析 运用分治算法解决此问题,是因为这种方法的优越行,下面通过时间复杂度的比较来说明。 通常算法,设置一个变量,等于需要比较的数组的第一个元素,然后依次与后面的n-1经行比较,需要比较n-1次得到最大元。同理,求得最小元的比较次数仍然是n-1次。设()n T 表示比较的次数则对于这种算法得到()n T 的值为 ()22n T n =- 分治算法求最大元比较 1 ()2()22 T n n T ??=?+?? 解方程结果为() 1.52T n n =-,虽然二者都是线性增长的,可是增长率要小一些。实际编程

-实验1分治法

一、实验目的 1.理解分治法的方法; 2. 掌握使用分治法解决一般问题的步骤; 3. 掌握分治算法求解数组的最大值和最小值的方法。 二、实验原理 在一个给定数组中查找最大值和最小值是一类常见的问题,也是解决其他一些算法的基础。 假设给定数组为a,数组中含有n个元素,一般的算法是在数组中进行直接 循环的次数在算法第2行给出,为(n-2)+1=n-1次,因此,算法元素比较总次数为2(n-1)次。 现在采用分治的思想,假设数组的长度为2的整数幂,将数组分割成两半,分别为a[0…(n/2)-1]和a[n/2…n-1],在每一半中分别查找最大值和最小值,并返回这两个最小值中的最小值以及两个最大值中的最大值。 假设给定数组为a,数组的下标上界和下界分别为low和high,则其算法伪 接比较数组的两个元素,选出最大值和最小值,此为函数的递归终止条件;代码第7行和第8行是两个递归调用,分别在数组的下标范围[low,mid]和 [mid+1,high]查找最小值和最大值,第9行比较两个最大值取其中较大者,第10行比较两个最小值取较大者。

代码的第2、9和10行涉及到元素的比较,第7、8行由于递归也产生元素比较,因此令算法总的元素比较次数为C(n),则有 ???>+==2 2)2/(221)(n n C n n C 若若 对递推式进行求解 2 2/3 2 2)2/( 2)2(2 2 2...22)2/(2 ... 2 48)8/(824)2)8/(2(4 2 4)4/(42)2)4/(2(22)2/(2)(1 1122111-=-+=+=+++++==+++=+++=++=++=+=∑-=-----n n C n C n C n C n C n C n C n C k k j j k k k k k 得到minmax 算法的元素比较总次数为3n/2-2,优于直接比较的性能。 三、实验内容及要求 1. 编写程序使用分治算法MINMAX 求解数组的最小值和最大值,并用实际数组对算法进行测试。 2. 要求算法中元素比较的次数为3n/2-2,在程序中元素比较的地方进行记录,并在程序末尾输出数组最大值和最小值以及元素比较次数。 四、实验步骤 1. 定义结构体类型或类,用以在函数的返回值同时返回数组的最大值和最小值。

算法分析与设计----大整数乘法代码

#include int main() { char a[100],b[100],s[202]; int n,i,j,g,t=0,k=1,temp; scanf("%d",&n); n--; scanf("%s%s",&a,&b); while(k<=2*n) { s[k]=0; temp=0; for(i=0;i<=n;i++) { for(j=0;j<=n;j++) { if((i+j)==k-1) temp+=(a[n-i]-48)*(b[n-j]-48); } } g=(temp+t)%10; t=(temp+t)/10;

s[k]=g; k++; } temp=0; for(i=0;i<=n;i++) { for(j=0;j<=n;j++) if((i+j)==k-1) temp+=(a[n-i]-48)*(b[n-j]-48); } temp+=t; printf("%d",temp); for(i=2*n;i>0;i--) printf("%d",s[i]); printf("\n"); return 0; } //两个100位以内的如果小了自己将数组改一下 设X和Y是两个n位的整数,假定n是2的整数次幂。把每个整数分为两部分,每部分为n/2位,则X和Y可重写为X=x1*10n/2+x0和Y=y1*10n/2+y0,X和Y的乘积可以计算为

X*Y= (x1*10n/2+x0)*( y1*10n/2+y0) = X1*Y1*10n+(( x1+x0)*( y1+y0)-x1*y1-x0*y0)* 10n/2+ x0*y0 由此体现了分治递归的思想,将大整数化小,规模也变小。 源代码如下: #include #include int n,x,y,rt;//全局变量 void input() { cout<<"两个乘数的位数是n,请输入n的值(n是2的整数次幂): "; cin>>n; cout<

幼儿园大班数学《乘法运算》教案

幼儿园大班数学《乘法运算》教案 活动目标: 1、使幼儿知道乘法的含义,认识到“求几个相同加数的和”用乘法计算比较简便. 2、认识乘号,会读、写乘法算式。 3、培养幼儿观察比较的能力. 活动重点: 知道乘法的含义,了解到“求几个相同加数的和”,用乘法计算比较简便. 活动难点: 乘法算式所表示的意思. 活动教具: 课件、字条、题卡、插板、电脑、铅笔、纸张作业。 活动过程: 一、开始部分 1、复习准备 口算两组题(要求读出算式,说出得数).

第一组第二组 7+8 3+3 6+4+3 5+5+5 7+2+6+1 4+4+4+4 1+3+4+5+2 2+2+2+2+2 幼儿按要求口答后,教师引导幼儿观察: 2、提问: 1)这两组题都是加法,但是它们有什么不同的地方? (第一组每道题的加数不相同,第二组的每道题的加数都相同)2)像第二组这样,加数都相同的加法,我们叫它“求相同加数的和”,也叫做“同数组成”。(出示字条) 3、(出示题卡)第1题3+3,相同加数是几,有几个3相加,这就是2个3.2个3是6,6里面有2个3。 第2题5+5+5,相同加数是几,有几个5相加,这就是3个5.3个5是15,15里面有()个5 第3题4+4+4+4,相同加数是几,有几个4相加,由幼儿说出4个4.4个4是(),16里面有()个4。 第4题2+2+2+2+2,相同加数是几,有几个2相加,由幼儿说出5个2.5个2是(),10里面有()个2 二、基本部分:

1.启发性谈话 像上面这样求几个相同加数的和,除了用加法计算外,还可以用一种简便方法,这种简便方法是什么呢?(引出乘法) 2.展示课件《乘法运算》 教师边展示边讲解边提问: 乘法和我们以前学过的加法、减法一样,也有一个运算符号叫乘号,乘号的写法是左斜右斜“×”.想一想说一说,乘号像什么(像汉语拼音中的×). (1)这个符号叫什么? 怎样写乘法算式呢?先看一看相同加数是几,相同加数是2,就写在乘号的前面,再数一数是几个2连加,把相同加数的个数5写在乘号的后面,2×5表示5个2连加,因此算式是2×5=10,读作2乘以5等于10.乘法口诀念做:二五一十。 (2)图片中先出现了几只鞋子,又出现了几只一共有多少只鞋子?盘子有几个?里面分别有多少萝卜?用加法算式怎么列?乘法怎么列算式?相同加数是几?有几个?这个乘法算式表示什么?几个几连加?用乘法口诀怎么念? 3、教师启发提问,图中共有几行?每行是几个?(引导幼儿观察图片的内容)根据课件图片插棋子列算式 4、拍手游戏.老师每次拍4下,拍3次.(由幼儿说出加法算式

用分治法求解棋盘覆盖问题

棋盘覆盖问题 问题描述: 在一个2k ×2k (k ≥0)个方格组成的棋盘中,恰有一个方格与其他方格不同,称该方格为特殊方格。显然,特殊方格在棋盘中出现的位置有4k 中情形,因而有4k 中不同的棋盘,图(a )所示是k=2时16种棋盘中的一个。棋盘覆盖问题要求用图(b )所示的4中不同形状的L 型骨牌覆盖给定棋盘上除特殊方格以外的所有方格,且热河亮哥L 型骨牌不得重复覆盖。 问题分析: K>0时,可将2k ×2k 的棋盘划分为4个2k-1×2k-1的子棋盘。这样划分后,由于原棋盘只有一个特殊方格,所以,这4个子棋盘中只有1个子棋盘中有特殊方格,其余3个子棋盘中没有特殊方格。为了将这3个没有特殊方格的子棋盘转化成为特殊棋盘,以便采用递归方法求解,可以用一个L 型骨牌覆盖这3个较小的棋盘的会合处,从而将原问题转化为4个较小规模的棋盘覆盖问题。递归地使用这种划分策略,直至将棋盘分割为1×1的子棋盘。 问题求解: 下面介绍棋盘覆盖问题中数据结构的设计。 (1) 棋盘:可以用一个二维数组board[size][size]表示一个棋盘,其中size=2k 。为了 在递归处理的过程中使用同一个棋盘,将数组board 设为全局变量。 (2) 子棋盘:整个棋盘用二维数组board[size][size]表示,其中的子棋盘由棋盘左上 角的下标tr 、tc 和棋盘大小s 表示。 (3) 特殊方格:用board[dr][dc]表示特殊方格,dr 和dc 是该特殊方格在二维数组 board 中的下标。 (4) L 型骨牌:一个2k ×2k 的棋盘中有一个特殊方格,所以,用到L 型骨牌的个数 为(4k -1)/3,将所有L 型骨牌从1开始连续编号,用一个全局变量tile 表示。 图(b ) 图 (a )

相关文档
最新文档