一、方程与方程组

1、一元高次方程的近似解

高次方程:当方程的未知数的次数大于2的时候,这个方程就叫作高次方程。例如:方程2x3+x-3=0就是一元三次方程。

求任意次的高次方程的根是很困难的,但是借助计算机可以求出方程的近似解。

使用计算机解方程,关键是通过数学分析得出计算公式和公式中变数的取值范围,在此基础上通过顺序查找或分治法枚举变量的可能值,将符合条件的变量值代入表达式,即可得出问题的解。

例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)之间一定有一个根。

算法分析

枚举根的值域中的每一个整数x(-100≤x≤100)。由于根与根之差的绝对值≥1,因此设定搜索区间[x1,x2],其中x1=x,x2=x+1。若

①f′(x1)=0,则确定x1为f′(x1)的根;

②f′(x1)* f′(x2)>0,则确定根x不在区间[x1,x2]内,设定[x1,x2+1]为下一个搜索区间;

③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)的根。由此得出算法:

function f(x:extended):extended;    {计算x3+b*x2+c*x+d}
  begin
    f:=x*x*x+b*x*x+c*x+d;
  end;{f}
begin

  输入方程中各项的系数a,b,c,d;{main}

b:=b/a;c:=c/a;d:=d/a;a:=1; {将方程变换为x3+b′ *x2+c′*x+d′=0的形式}
  for x:=–100 to 100 do      {枚举每一个可能的根}
  begin
    x1:=x;x2:=x+1;             {确定根的可能区间}
    if f(x1)=0                 {若x1为根,则输出}
    then write(x1:0:2,’ ‘)
    else if (f(x1)*f(x2)<0)     {若根在区间[x1,x2]中}
         then begin
               while x2-x1>=0.001 do{若区间[x1,x2]不满足精度要求,则循环}
                 begin
                   xx:=(x2+x1)/2;  {计算区间[x1,x2]的中间位置}
                   if f(x1)*f(xx)<=0    {若根在左区间,则调整右指针}
                   then x2:=xx
                   else x1:=xx;         {若根在右区间,则调整左指针}
                 end;{while}
              write(x1:0:2,’ ‘);{区间[x1,x2]满足精度要求,确定x1为根}
        end;{then}
      end;{for}
 end.

2、不定方程的整数解

二元一次不定方程:形如ax+by=c(x,y为未知数,系数a,b不都是零)的方程叫作二元一次不定方程。例如方程2x-y=1中有两个未知数,但只有一个方程,它的解有无数多个。所以叫作不定方程。通常我们求不定方程的解限定在整数范围内。

二元一次不定方程的求解定理:设二元一次不定方程ax+by=c;其中a,b,c都是正整数,且(a,b)=1;有一组正整数解x=x0,y=y0,则方程式的一切整数解可以表示成

 

 

 

4 把118分成两个整数,一个为11的倍数,另一个为17的倍数。

解 设所求的两个数为x,y,由题意得

                            11x+17y=118

由观察知x=3,y=5是方程的一组解,所以方程的整数解为:

 

     

 

利用计算机求不定方程的整数解,主要采用枚举法。首先要根据问题的条件确定解的范围,然后利用循环搜索,在给定的范围内寻找满足不定方程的所有解。看下面的具体例子。

例5 给定一个二元一次方程aX+bY=c。从输入文件input.txt中读入a,b,c,n,m(读入数据为integer范围,仅一行且数据之间用空格分隔)的数值,求X在[n,m],Y在[n,m]范围内的所有整数解的个数。所求个数写到输出文件output.txt。

参考程序

var a,b,c,n,m:integer;
   i,j:integer;
   sum:longint;
begin
  assign(input,’input.txt’);
  assign(output,’output.txt’);
  reset(input);
  rewrite(output);
  read(a,b,c,n,m);
  sum:=0;
  for i:=n to m do
    for j:=n to m do
      if (a*i+b*j)=c then inc(sum);
  write(sum);
  close(input);
  close(output);
end.

二、矩阵

1、定义

矩阵就是排成行与列的数的阵列,一个m行n列的矩阵可以用符号形式表示为:

 

A=

 

和行、各列上的数叫作矩阵的元素。例如:

 

 

当一个矩阵行数等于列数时,叫作方阵。例如:

 

 

2 几种特殊的矩阵

行矩阵:仅有一行的矩阵。例如:[1,0,0]

列矩阵:仅有一列的矩阵。例如:

 

单位矩阵:主对角线上的元素皆为1,其他元素均为0的矩阵,记为I。例如:

    

 

对称矩阵:所有主对角线右上方的元素和主对角线左下方的元素对应相等的矩阵。例如:

 

(3)矩阵的运算

①矩阵的相等。当两个矩阵的对应元素都相等,则称这两个矩阵相等。例如:

 

 

 

 

 

②矩阵的加减运算。两个矩阵的行数和列数分别相等时,可以相加、相减。两个矩阵相加减时,结果还是矩阵,它的各个元素等于两个矩阵对应元素相加减所得的值。例如:

 

 

 

 

 

③一个数和矩阵相乘。一个数和矩阵相乘,仍是一个矩阵,只要把该数与矩阵中的每个元素相乘即可。例如:

 

 

④矩阵的乘法运算。第一个矩阵的行数等于第二个矩阵的列数时,这两个矩阵可以相乘。例如:

 已知

 

 

 

 

 

参考程序

var i,j,k:integer;
   a,b,c:array[1..3,1..3] of integer;
begin
  for i:=1 to 3 do
for j:=1 to 2 do
  read(a[i,j]);
  for i:=1 to 2 do
for j:=1 to 3 do
  read(b[i,j]);
  for i:=1 to 3 do
for j:=1 to 3 do
  begin
    t:=0;
    for k:=1 to 2 do t:=t+a[i,k]*b[k,j];
    c[i,j]:=t;
  end;
  for i:=1 to 3 do
begin
  for j:=1 to 3 do
    write(c[i,j]);
  writeln;
end;
  end.

⑤矩阵的转置。矩阵A的转置就是将矩阵A的行和列进行调换,形成一个新的矩阵,记作A′。例如:

 

 

⑥逆矩阵。如果一个矩阵乘以矩A,得到一个单位矩阵I,则这个矩阵叫作矩阵A的逆矩阵,表示为A-1。例如:设

 

 

因为

 

 

所以B=A-1。

⑦矩阵的初等变换。如果一个矩阵相应地进行以下三种变形:

(ⅰ)用一个非零常数乘以矩阵某一行的所有元素;

(ⅱ)用一个非零常数乘以矩阵的某一行的所有元素,加到另一行的对应元素上去;

(ⅲ)互换两行。

则这三种变换叫作矩阵的行的初等变换。一个矩阵经过初等变换后,就变为另一个不同的矩阵。例如:

 

 

例6 定义:f0=f1=1,fn=fn-1+fn-2(n≥2)。{fi}称为Fibonacci数列.

输入n,求fn mod q ,其中1≤q≤30000。

输入数据

第一行一个数t(1≤t≤10000)。

以下t行,每行两个数:n,q(n≤109,1≤q≤30000)。

输出数据

文件包含1行,每行对应一个答案。

输入输出示例

fib.in

3

6 2

7 3

7 11

fib.out

1

0

10 

算法分析

用矩阵乘法来解决此题

因为,

 

 

 

 

    所以     n

    

要求fn,只需要先求 n,根据矩阵对应元素相等即可求得fn 。求

n

利用矩阵乘法规则即可。

参考程序

type
  integer=longint;
  tarray=array[1..2,1..2] of integer;
var
  sum,tum,n,q:integer;
  tot,a:tarray;
procedure mul(var c:tarray;a,b:tarray);
  var
    i,j,k:integer;
  begin
    fillchar(c,sizeof(c),0);
    for i:=1 to 2 do
      for j:=1 to 2 do
        for k:=1 to 2 do 
          c[i][j]:=(c[i][j])+a[i][k]*b[k][j] mod q;
  end;{mul}
begin
  assign(input,’fib.in’);
  reset(input);
  assign(output,’fib.out’);
  rewrite(output);
  read(sum);
  for turn:=1 to sum do
    begin
      read(n,q);
      if (q=1) then
        writeln(0)
      elsle
        begin
          tot[1][1]:=1;
          tot[2][2]:=1;
          tot[1][2]:=0;
          tot[2][1]:=0;
          a[1][1]:=0;
          a[1][2]:=1;
          a[2][1]:=1;
          a[1][2]:=1;
          while (n>0) do
            begin
              if (odd(n)) then
                mul(tot,tot,a);
              mul(a,a,a);
              n:=n div 2;
            end;
          writeln(tot[2][2]);
        end;
      end;
    close(output);
    close(input);
  end.

优化另解

program a1;
var i,j,k,top,t,n,f,m,x,y,p:integer;
   a,b,c,d:array[1..2,1..2] of longint;
   q,s:array[1..1000]of integer;
begin
readln(x);
d[1,1]:=1;d[1,2]:=1;
b[1,1]:=0;b[1,2]:=1;
i:=2;
for j:=1 to 2 do
  b[i,j]:=1;
top:=0;
for y:=1 to x do
begin
a:=d;m:=0;
readln(n,p);
while m<>n do
begin
i:=1;
for j:=1 to 2 do
  begin
    t:=0;
    for k:=1 to 2 do
    t:=t+a[i,k]*b[k,j];
    c[i,j]:=t;
  end;
  a:=c;
  m:=m+1;
  end;
  m:=c[1,1];top:=top+1;
  q[top]:=m;s[top]:=p;
  end;
  for i:=1 to top do
    writeln(q[i] mod s[i]);
  end.