第七章 分治算法.

Slides:



Advertisements
Similar presentations
1 、谁能说说什么是因数? 在整数范围内( 0 除外),如果甲数 能被乙数整除,我们就说甲数是乙数的 倍数,乙数是甲数的因数。 如: 12÷4=3 4 就是 12 的因数 2 、回顾一下,我们认识的自然数可以分 成几类? 3 、其实自然数还有一种新的分类方法, 你知道吗?这就是我们今天这节课的学.
Advertisements

因数与倍数 2 、 5 的倍数的特征
摆一摆,想一想. 棋子个数数的个数 摆出的数 、 10 2 、 11 、 20 3 、 12 、 21 、 30 4 、 13 、 22 、 31 、 40 5 、 14 、 23 、 32 、 41 、
3 的倍数特征 抢三十
质数和合数 2 的因数( ) 6 的因数( ) 10 的因数 ( ) 12 的因数 ( ) 14 的因数 ( ) 11 的因数 ( ) 4 的因数( ) 9 的因数( ) 8 的因数( ) 7 的因数( ) 1 、 2 、 3 、 4 、 6 、 12 1 、 11 1 、 2 、 5 、 10.

3 的倍数的特征 的倍数有 : 。 5 的倍数有 : 。 既是 2 的倍数又是 5 的倍数有 : 。 12 , 18 , 20 , 48 , 60 , 72 , , 25 , 60 ,
2 和 5 的倍数的特征 运动热身 怎样找一个数的倍数? 从小到大写出 2 的倍数( 10 个): 写出 5 的倍数( 6 个) 2 , 4 , 6 , 8 , 10 , 12 , 14 , 16 , 18 , 20 5 , 10 , 15 , 20 , 25 , 30.
2.8 函数的微分 1 微分的定义 2 微分的几何意义 3 微分公式与微分运算法则 4 微分在近似计算中的应用.
第四单元 100 以内数的认识
冀教版四年级数学上册 本节课我们主要来学习 2 、 3 、 5 的倍数特征,同学们要注意观察 和总结规律,掌握 2 、 3 、 5 的倍 数分别有什么特点,并且能够按 要求找出符合条件的数。
做个百数表. 把表格填完整,仔细观察,你还有什么新发现 ?
2 , 5 的倍数的特征. 我们可以先写出几个 5 的 倍数来看看。 对,先研究小范围的数, 再进行推广验证。
2 、 5 的倍数的特征. 目标 重点 难点 关键词 2 、 5 的倍数的特征 1 、发现 2 和 5 的倍数的特征。 2 、知道什么是奇数和偶数。 能判断一个数是不是 2 或 5 的倍数。 能判断一个数是奇数还是偶数。 奇数、偶数。 返回返回 目录目录 前进前进.
第四单元 100 以内数的认识
练一练: 在数轴上画出表示下列各数的点, 并指出这些点相互间的关系: -6 , 6 , -3 , 3 , -1.5, 1.5.
2 、 5 的倍数特征 集合 2 的倍数(要求) 在百数表上依次将 2 的倍数找出 并用红色的彩笔涂上颜色。
§3.4 空间直线的方程.
3.4 空间直线的方程.
代数方程总复习 五十四中学 苗 伟.
圆的一般方程 (x-a)2 +(y-b)2=r2 x2+y2+Dx+Ey+F=0 Ax2+Bxy+Cy2+Dx+Ey+ F=0.
18.2一元二次方程的解法 (公式法).
程序设计实习 3月份练习解答
C语言程序设计.
小学生游戏.
在数轴上比较数的大小.
走进编程 程序的顺序结构(二).
第一单元 初识C程序与C程序开发平台搭建 ---观其大略
第4章 非线性规划 一维搜索方法 2011年11月.
What have we learned?.
切換Dev c++顯示語言 工具->環境選項(V)->介面->language (Chinese TW)
2.1.2 空间中直线与直线 之间的位置关系.
一元弱酸pH值的计算机数值求解 化学系1班 殷乃宁.
第一章 函数与极限.
人教版五年级数学上册第四单元 解方程(一) 马郎小学 陈伟.
计算.
C++语言程序设计 C++语言程序设计 第七章 类与对象 第十一组 C++语言程序设计.
数列.
顺序表的删除.
线 性 代 数 厦门大学线性代数教学组 2019年4月24日6时8分 / 45.
第四章 一次函数 4. 一次函数的应用(第1课时).
C++语言程序设计 C++语言程序设计 第三章 控制语句 第十一组 C++语言程序设计.
物件導向程式設計 CH2.
用计算器开方.
成绩是怎么算出来的? 16级第一学期半期考试成绩 班级 姓名 语文 数学 英语 政治 历史 地理 物理 化学 生物 总分 1 张三1 115
第4章 Excel电子表格制作软件 4.4 函数(一).
C qsort.
正切函数的图象和性质 周期函数定义: 一般地,对于函数 (x),如果存在一个非零常数T,使得当x取定义域内的每一个值时,都有
小数的大小比较 仙岩镇第二小学 陈曼丽.
第九节 赋值运算符和赋值表达式.
第16讲 相似矩阵与方阵的对角化 主要内容: 1.相似矩阵 2. 方阵的对角化.
用穷举法设计程序 南京师范大学 教育技术系 倪佳慧
§6.7 子空间的直和 一、直和的定义 二、直和的判定 三、多个子空间的直和.
3.16 枚举算法及其程序实现 ——数组的作用.
1.设A和B是集合,证明:A=B当且仅当A∩B=A∪B
第4课时 绝对值.
多层循环 Private Sub Command1_Click() Dim i As Integer, j As Integer
第七、八次实验要求.
分数再认识三 真假带分数的练习课.
第15讲 特征值与特征向量的性质 主要内容:特征值与特征向量的性质.
找 因 数.
数据表示 第 2 讲.
第十七讲 密码执行(1).
插入排序的正确性证明 以及各种改进方法.
§4.5 最大公因式的矩阵求法( Ⅱ ).
第二次课后作业答案 函数式编程和逻辑式编程
8、9的认识 一年级组 李 晶.
一元一次方程的解法(-).
§2 自由代数 定义19.7:设X是集合,G是一个T-代数,为X到G的函数,若对每个T-代数A和X到A的函数,都存在唯一的G到A的同态映射,使得=,则称G(更严格的说是(G,))是生成集X上的自由T-代数。X中的元素称为生成元。 A变, 变 变, 也变 对给定的 和A,是唯一的.
学习目标 1、什么是列类型 2、列类型之数值类型.
Presentation transcript:

第七章 分治算法

所谓分治就是指的分而治之,即将较大规模的问题分解成几个较小规模的问题,通过对较小规模问题的求解达到对整个问题的求解。当我们将问题分解成两个较小问题求解时的分治方法称之为二分法。 你们玩过猜数字的游戏吗?你的朋友心里想一个1000以内的正整数,你可以给出一个数字x,你朋友只要回答“比x大”或者“比x小”或者“猜中”,你能保证在10次以内猜中吗?运气好只要一次就猜中。 开始猜测是1到1000之间,你可以先猜500,运气好可以一次猜中,如果答案比500大,显然答案不可能在1到500之间,下一次猜测的区间变为501到1000,如果答案比500小,那答案不可能在500到1000之间,下一次猜测的区间变为1到499。只要每次都猜测区间的中间点,这样就可以把猜测区间缩小一半。由于 ,因此不超过10次询问区间就可以缩小为1,答案就会猜中了,这就是二分的基本思想。 每一次使得可选的范围缩小一半,最终使得范围缩小为一个数,从而得出答案。假设问的范围是1到n,根据 ,所以我们只需要问O(logn)次就能知道答案了。 需要注意的是使用二分法有一个重要的前提,就是有序性,下面通过几个例子来体会二分法的应用。

例7.1 找数 描述: 给一个长度为n的单调递增的正整数序列,即序列中每一个数都比前一个数大。有m个询问,每次询问一个x,问序列中最后一个小于等于x的数是什么? 输入: 第一行两个整数n,m。 接下来一行n个数,表示这个序列。 接下来m行每行一个数,表示一个询问。 输出: 输出共m行,表示序列中最后一个小于等于x的数是什么。假如没有输出-1。 样例输入: 5 3 1 2 3 4 6 5 1 3 样例输出: 4

分析: 我们用Left表示询问区间的左边界,用Right表示询问区间的右边界,[Left,Right]组成询问区间。一开始Left=1,Right=n,我们可以把原始序列的左边想象成若干个无穷小的数,把序列的右边想象成无穷大的数,这样比较好理解。序列已经按照升序排好,保证了二分的有序性。 每一次二分,我们这样来做: ①取区间中间值Mid=(Left+Right)/2; ②判断Mid与x的关系,如果a[Mid]>x,由于序列是升序排列,所以区间[Mid,Right]都可以被排除,修改右边界Right=Mid-1; ③如果a[Mid]<=x,修改左边界Left=Mid+1; 重复执行二分操作直到Left>Right。 下面我们来分析答案的情况。循环结束示意图如下:LeftRight大于x小于等于x 最终循环结束时一定是Left=Right+1,根据二分第②步的做法我们知道Right的右边一定都是大于x的,而根据第③步我们可以知道Left左边一定是小于等于x的。 所以,一目了然,最终答案是Right指向的数。Right=0就是题目中输出-1的情况。

程序如下: #include <iostream> using namespace std; int n,m,a[110000]; int main() { cin >> n >> m; for (int i=1; i<=n; i++) cin >> a[i]; a[0]=-1; for (int i=1; i<=m; i++) { int x; int left=1,right=n,mid; cin >> x; while (left <= right) { mid = (left + right) / 2; if (a[mid] <= x) left = mid + 1; else right = mid - 1; } cout << a[right] << endl; } return 0; }

例7. 2 快速排序(Quicksort) 快速排序由C. A. R 例7.2 快速排序(Quicksort) 快速排序由C. A. R. Hoare在1962年提出。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。 设要排序的数组是A[0]……A[N-1],首先任意选取一个数据(通常选用数组的中间数)作为关键数据,然后将所有比它小的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一趟快速排序。值得注意的是,快速排序不是一种稳定的排序算法,也就是说,多个相同的值的相对位置也许会在算法结束时产生变动。 一趟快速排序的算法是: 1.设置两个变量i、j,排序开始的时候:i=0,j=N-1; 2.以数组中任意元素作为关键数据(一般以数组中间元素作为关键数据),赋值给key,可以是key=A[(i+j)/2]; 3.从j开始向前搜索,即由后开始向前搜索(j--),找到第一个小于等于key的值A[j]; 4.从i开始向后搜索,即由前开始向后搜索(i++),找到第一个大于等于key的A[i]; 5.交换A[i]和A[j]的值,同时i++, j--; 6.重复第3、4、5步,直到i>j; 例如有8个元素需要排序: 6 10 11 8 4 1 9 7

一趟快速排序后: 此时i>j,并且i左边的数字都小于等于key,j右边的数字都大于等于key,进而接下来可以分别对左边段[0, j]和右边段[i,N-1]利用同样的方法排序。

【程序实现】 void qsort(int le,int ri) { int i=le, j=ri, mid=a[(le+ri)/2]; while(i<=j) //注意这里要有等号 { while(a[i]<mid) i++; //在左边找大于等于mid的数 while(a[j]>mid) j--; //在右边找小于等于mid的数 if(i<=j) { swap(a[i],a[j]); //交换 i++, j--; //继续找 } } if(le<j) qsort(le,j); //分别递归继续排序 if(i<ri) qsort(i,ri); } 快速排序(Quicksort)是对冒泡排序的一种改进,快速排序的时间复杂度是O(nlogn),速度快,但它是不稳定的排序方法。就平均时间而言,快速排序是目前被认为是最好的一种内部排序的方法。但快速排序需要一个栈空间来实现递归,若每一趟排序都将记录序列均匀地分割成长度相近的两个子序列,则栈的最大深度为log(n+1)。

【例3】一元三次方程求解 有形如:ax3+bx2+cx+d=0这样的一个一元三次方程。给出该方程中各项的系数(a,b,c,d均为实数),并约定该方程存在三个不同实根(根的范围在-100至100之间),且根与根之差的绝对值≥1。 要求由小到大依次在同一行输出这三个实根(根与根之间留有空格),并精确到小数点后2位。 提示:记方程f(x)=0,若存在2个数x1和x2,且x1<x2,f(x1)*f(x2)<0,则在(x1,x2)之间一定有一个根。 输入:a,b,c,d 输出:三个实根(根与根之间留有空格) 【输入输出样例】 输入:1 -5 -4 20 输出:-2.00 2.00 5.00 【算法分析】 这是一道有趣的解方程题。为了便于求解,设方程f(x)=ax3+bx2+cx+d=0,设根的值域(-100至100之间)中有x, 其左右两边相距0.0005的地方有x1和x2两个数,即 x1=x-0.0005,x2=x+0.0005。x1和x2间的距离(0.001)满足精度要求(精确到小数点后2位)。若出现如图1所示的两种情况之一,则确定x为f(x)=0的根。

有两种方法计算f(x)=0的根x: 1.枚举法 根据根的值域和根与根之间的间距要求(≥1),我们不妨将根的值域扩大100倍(-10000≤x≤10000),依次枚举该区间的每一个整数值x,并在题目要求的精度内设定区间:x1=,x2=。若区间端点的函数值f(x1)和f(x2)异号或者在区间端点x1的函数值f(x1)=0,则确定为f(x)=0的一个根。 由此得出算法: 输入方程中各项的系数a,b,c,d ; for (x=-10000;x<=10000;x++) //枚举当前根*100的可能范围 { x1=(x-0.05)/100;x2=(x+0.05)/100;//在题目要求的精度内设定区间 if (f(x1)*f(x2)<0||f(x1)==0) //若在区间两端的函数值异号或在x1处 的函数值为0,则确定x/100为根 printf(“%.2f”,x/100); } 其中函数f(x)计算x3+b*x2+c*x+d: double f(double x) //计算x3+b*x2+c*x+d f=x*x*x+b*x*x+c*x+d; } //f函数

2.分治法 枚举根的值域中的每一个整数x(-100≤x≤100)。由于根与根之差的绝对值≥1,因此设定搜索区间[x1,x2],其中x1=x,x2=x+1。若 ⑴f(x1)=0,则确定x1为f(x)的根; ⑵f(x1)*f(x2)>0,则确定根x不在区间[x1,x2]内,设定[x2,x2+1]为下一个搜索区间 ⑶f(x1)*f(x2)<0,则确定根x在区间[x1,x2]内。 如果确定根x在区间[x1,x2]内的话(f(x1)*f(x2)<0),如何在该区间找到根的确切位置。采用二分法,将区间[x1,x2]分成左右两个子区间:左子区间[x1,x]和右子区间[x,x2](其中x=): 如果f(x1)*f(x)≤0,则确定根在左区间[x1,x]内,将x设为该区间的右指针(x2=x),继续对左区间进行对分;如果f(x1)*f(x)>0,则确定根在右区间[x,x2]内,将x设为该区间的左指针(x1=x),继续对右区间进行对分; 上述对分过程一直进行到区间的间距满足精度要求为止(x2-x1<0.001)。此时确定x1为f(x)的根。

由此得出算法: 输入方程中各项的系数a,b,c,d ; { for (x=-100;x<=100;x++) //枚举每一个可能的根 x1=x;x2=x+1; //确定根的可能区间 if (f(x1)==0) printf("%.2f ",x1); //若x1为根,则输出 else if (f(x1)*f(x2)<0) //若根在区间[x1,x2]中 while (x2-x1>=0.001) //若区间[x1,x2]不满足精度要求,则循环 xx=(x2+x1)/2; //计算区间[x1,x2]的中间位置 if ((f(x1)*f(xx))<=0) //若根在左区间,则调整右指针 x2=xx; else x1=xx; //若根在右区间,则调整左指针 } printf("%.2f ",x1); //区间[x1,x2]满足精度要求,确定x1为根 cout<<endl; double f(double x) //将x代入函数 return (x*x*x*a+b*x*x+x*c+d); 其中f(x)的函数说明如枚举法所示。

【例4】、循环比赛日程表(match) 【问题描述】 设有N个选手进行循环比赛,其中N=2M,要求每名选手要与其他N-1名选手都赛一次,每名选手每天比赛一次,循环赛共进行N-1天,要求每天没有选手轮空。 输入:M 输出:表格形式的比赛安排表 【样例输入】match.in 3 【样例输出】match.out 1 2 3 4 5 6 7 8 2 1 4 3 6 5 8 7 3 4 1 2 7 8 5 6 4 3 2 1 8 7 6 5 5 6 7 8 1 2 3 4 6 5 8 7 2 1 4 3 7 8 5 6 3 4 1 2 8 7 6 5 4 3 2 1

【问题分析】 以M=3(即N=23=8)为例,可以根据问题要求,制定出如下图所示的一种方案: 以表格的中心为拆分点,将表格分成A、B、C、D四个部分,就很容易看出有A=D,B=C,并且,这一规律同样适用于各个更小的部分。 设有n个选手的循环比赛,其中n=2m,要求每名选手要与其他n-1名选手都赛一次。每名选手每天比赛一次,循环赛共进行n-1天。要求每天没有选手轮空.以下是八名选手时的循环比赛表,表中第一行为八位选手的编号,下面七行依次是每位选手每天的对手。

1 2 3 4 5 6 7 8 2 1 4 3 6 5 8 7 3 4 1 2 7 8 5 6 4 3 2 1 8 7 6 5 5 6 7 8 1 2 3 4 6 5 8 7 2 1 4 3 7 8 5 6 3 4 1 2 8 7 6 5 4 3 2 1 【算法分析】 从八位选手的循环比赛表中可以看出,这是一个具有对称性的方阵,可以把方阵一分为四来看,那么左上角的4*4的方阵就是前四位选手的循环比赛表,而右上角的4*4的方阵就是后四位选手的循环比赛表,它们在本质上是一样的,都是4个选手的循环比赛表,所不同的只是选手编号不同而已,将左上角中方阵的所有元素加上4就能得到右上角的方阵.下方的两个方阵表示前四位选手和后四位选手进行交叉循环比赛的情况,同样具有对称性,将右上角方阵复制到左下角即得到1,2,3,4四位选手和5,6,7,8四位选手的循环比赛表,根据对称性, 右下角的方阵应与左上角的方阵相同.这样,八名选手的循环比赛表可以由四名选手的循环比赛表根据对称性生成出来.同样地, 四名选手的循环比赛表可以由二名选手的循环比赛表根据对称性生成出来,而两名选手的循环比赛表可以说是已知的,这种程序设计方法叫做分治法,其基本思想是把一个规模为n的问题分成若干个规模较小的问题,使得从这些较小问题的解易于构造出整个问题的解。 程序中用数组matchlist记录n名选手的循环比赛表, 整个循环比赛表从最初的1*1的方阵按上述规则生成出2*2 的方阵, 再生成出4*4 的方阵,……,直到生成出整个循环比赛表为止.变量half表示当前方阵的大小,也是要生成的下一个方阵的大小的一半 。

【参考程序】 #include<cstdio> const int MAXN=33,MAXM=5; int matchlist[MAXN][MAXN]; int m; int main() { printf("Input m:"); scanf("%d",&m); int n=1<<m,k=1,half=1; // 1<<m 相当于 2^m matchlist[0][0]=1; while (k<=m) for (int i=0;i<half;i++) //构造右上方方阵 for (int j=0;j<half;j++) matchlist[i][j+half]=matchlist[i][j]+half; for (int i=0;i<half;i++) //对称交换构造下半部分方阵 matchlist[i+half][j]=matchlist[i][j+half]; //左下方方阵等于右上方方阵 matchlist[i+half][j+half]=matchlist[i][j]; //右下方方阵等于左上方方阵 }

half*=2; k++; } for (int i=0;i<n;i++) { for (int j=0;j<n;j++) printf("%4d",matchlist[i][j]); putchar('\n'); return 0;

输入b,p,k的值,求b^p mod k的值。其中b,p,k*k为长整形数。 【输入样例】mod.in 2 10 9 【问题描述】 输入b,p,k的值,求b^p mod k的值。其中b,p,k*k为长整形数。 【输入样例】mod.in 2 10 9 【输出样例】mod.out 2^10 mod 9=7 【算法分析】 本题主要的难点在于数据规模很大(b,p都是长整型数),对于b^p显然不能死算,那样的话时间复杂度和编程复杂度都很大。 下面先介绍一个原理:A*B%K = (A%K )*(B% K )%K。显然有了这个原理,就可以把较大的幂分解成较小的,因而免去高精度计算等复杂过程。那么怎样分解最有效呢?

显然对于任何一个自然数P,有P=2. P/2 + P%2,如19=2. 19/2 + 19%2=2 显然对于任何一个自然数P,有P=2 * P/2 + P%2,如19=2 * 19/2 + 19%2=2*9+1,利用上述原理就可以把B的19次方除以K的余数转换为求B的9次方除以K的余数,即B19=B2*9+1=B*B9*B9,再进一步分解下去就不难求得整个问题的解。

【参考程序】 #include<iostream> #include<cstdio> using namespace std; int b,p,k,a; int f(int p) //利用分治求b^p % k { if (p==0) return 1; // b^0 %k=1 int tmp=f(p/2)%k; tmp=(tmp*tmp) % k; // b^p %k=(b^(p/2))^2 % k if (p%2==1) tmp=(tmp * b) %k; //如果p为奇数,则 b^p % return tmp; //k=((b^(p/2))^2)* b%k } int main() cin>>b>>p>>k; //读入3个数 int tmpb=b; //将b的值备份 b%=k; //防止b太大 printf("%d^%d mod %d=%d\n",tmpb,p,k,f(p)); //输出 return 0;

【例8】、黑白棋子的移动(chessman) 【问题描述】 有2n个棋子(n≥4)排成一行,开始位置为白子全部在左边,黑子全部在右边,如下图为n=5的情形: ○○○○○●●●●● 移动棋子的规则是:每次必须同时移动相邻的两个棋子,颜色不限,可以左移也可以右移到空位上去,但不能调换两个棋子的左右位置。每次移动必须跳过若干个棋子(不能平移),要求最后能移成黑白相间的一行棋子。如n=5时,成为: ○●○●○●○●○● 任务:编程打印出移动过程。 【输入样例】chessman.in 7 【输出样例】chessman.out step 0:ooooooo*******-- step 1:oooooo--******o* step 2:oooooo******--o* step 3:ooooo--*****o*o* step 4:ooooo*****--o*o* step 5:oooo--****o*o*o* step 6:oooo****--o*o*o* step 7:ooo--***o*o*o*o* step 8:ooo*o**--*o*o*o* step 9:o--*o**oo*o*o*o* step10:o*o*o*--o*o*o*o* step11:--o*o*o*o*o*o*o*

【算法分析】 我们先从n=4开始试试看,初始时: ○○○○●●●● 第1步:○○○——●●●○● {—表示空位} 第2步:○○○●○●●——● 第3步:○——●○●●○○● 第4步:○●○●○●——○● 第5步:——○●○●○●○● 如果n=5呢?我们继续尝试,希望看出一些规律,初始时: ○○○○○●●●●● 第1步:○○○○——●●●●○● 第2步:○○○○●●●●——○● 这样,n=5的问题又分解成了n=4的情况,下面只要再做一下n=4的5个步骤就行了。同理,n=6的情况又可以分解成n=5的情况,……,所以,对于一个规模为n的问题,我们很容易地就把他分治成了规模为n-1的相同类型子问题。 数据结构如下:数组c[1..max]用来作为棋子移动的场所,初始时,c[1]~c[n]存放白子(用字符o表示),c[n+1]~c[2n]存放黑子(用字符*表示),c[2n+1],c[2n+2]为空位置(用字符—表示)。最后结果在c[3]~c[2n+2]中。

【参考程序】 #include<iostream> using namespace std; int n,st,sp; char c[101]; void print() //打印 { int i; cout<<"step "<<st<<':'; for (i=1;i<=2*n+2;i++) cout<<c[i]; cout<<endl; st++; } void init(int n) //初始化 st=0; sp=2*n+1; for (i=1;i<=n;i++) c[i]='o'; for (i=n+1;i<=2*n;i++) c[i]='*'; c[2*n+1]='-';c[2*n+2]='-'; print();

void move(int k) //移动一步 { int j; for (j=0;j<=1;j++) c[sp+j]=c[k+j]; c[k+j]='-'; } sp=k; print(); void mv(int n) //主要过程 int i,k; if (n==4) //n等于4的情况要特殊处理 move(4); move(8); move(2); move(7); move(1); else move(n); move(2*n-1); mv(n-1); int main() cin>>n; init(n); mv(n);

【问题描述】 求方程f(x)=2^x+3^x-4^x=0在[1,2]内的根。 提示:2x可以表示成exp(x*log(2))的形式。 【上机练习】 1、方程f(x)的根 【问题描述】 求方程f(x)=2^x+3^x-4^x=0在[1,2]内的根。 提示:2x可以表示成exp(x*log(2))的形式。 【输入格式】 输入:[1,2]的区间值。 【输出格式】 输出:方程f(x)=0的根,x的值精确小数点10位。 【输入样例】 1 2 【输出样例】 1.5071105957 2、求一元三次方程的解 【问题描述】 有形如: ax3+bx2+cx+d=0一元三次方程。给出该方程中各项的系数 (a, b, c, d  均为实数 ),并约定该方程存在三个不同实根 (根的范围在 -100至 100之间 ),且根与根之差的绝对值 >=1。要求由小到大依次在同一行上输出这三个实根。 【输入格式】 输入:a,b,c,d 【输出格式】 输出: 三个实根(根与根之间留有空格) 【输入样例】Equ.in 1 –5 –4 20 【输出样例】Equ.out -2.00 2.00 5.00

3、求逆序对 给定一个序列a1,a2,…,an,如果存在i<j并且ai>aj,那么我们称之为逆序对,求逆序对的数目。 【输入格式】 第一行为n,表示序列长度,接下来的n行,第i+1行表示序列中的第i个数。 【输出格式】 所有逆序对总数。 【输入样例】deseq. in 4 3 2 【输出样例】deseq.out 【数据范围】 N<=105,Ai<=105。

4、麦森数(mason) 【问题描述】 形如2P-1的素数称为麦森数,这时P一定也是个素数。但反过来不一定,即如果P是个素数,2P-1不一定也是素数。到1998年底,人们已找到了37个麦森数。最大的一个是P=3021377,它有909526位。麦森数有许多重要应用,它与完全数密切相关。 任务:从文件中输入P(1000<P<3100000),计算2P-1的位数和最后500位数字(用十进制高精度数表示)。 【输入格式】 文件中只包含一个整数P(1000<P<3100000)。 【输出格式】 第一行:十进制高精度数2P-1的位数; 第2-11行:十进制高精度数2P-1的最后500位数字(每行输出50位,共输出10行,不足500位时高位补0); 不必验证2P-1与P是否为素数。 【输入样例】mason.in 1279 【输出样例】mason.out 386 00000000000000000000000000000000000000000000000000 00000000000000104079321946643990819252403273640855 38615262247266704805319112350403608059673360298012 23944173232418484242161395428100779138356624832346 49081399066056773207629241295093892203457731833496 61583550472959420547689811211693677147548478866962 50138443826029173234888531116082853841658502825560 46662248318909188018470682222031405210266984354887 32958028878050869736186900714720710555703168729087