第2讲 穷举 下载本文

内容发布更新时间 : 2024/5/16 4:07:15星期一 下面是文章的全部内容请认真阅读。

(式中代数和表达式中符号为二个“+”号后一个“-”号) 2. 设计要点 一般地,解不等式

d?1?12?13?14?15?16???1n (4)

(其中d为从键盘输入的正数)

式中符号为二个“+”号后一个“-”号,即分母能被3整除时为“-”,式中出现减运算,导致不等式的解可能分段。

设置条件循环,每三项(包含二正一负)一起求和,得一个区间解。 然后回过头来一项项求和,得个别离散解。 (2) 程序设计

// 解不等式:d<1+1/2-1/3+1/4+1/5-1/6+...+-1/n #include void main() { long d,n,k; double s;

printf(\请输入正整数d: \ scanf(\

printf(\?+-1/n 的解:\ n=1;s=0; while(1)

{ s=s+1.0/n+1.0/(n+1)-1.0/(n+2); if(s>d) break; n=n+3;

}

printf(\得一个区间解 k=1;s=0; while(k

{ if(k%3>0) s=s+1.0/k; else s=s-1.0/k;

if(s>d) // 得一个离散解 printf(\ k++; } }

(3) 程序运行示例 请输入正整数d: 5

5<1+1/2-1/3+1/4+1/5-1/6+?+-1/n 的解:

13

n>=203938 n=203936

注意:前一个是区间解,后一个是离散解。要特别注意,不要把后一个解遗失。

2.5 求最值

求最值通常是程序设计最具魅力的课题之一。本节介绍两个有趣的最值案例求解,是运用穷举求解的典型手法。

2.5.1 基于素数的代数和

1. 案例提出 定义和:

s(n)?13?35?57?79?911?1113???2n?12n?1

(和式中第k项±(2k-1)/(2k+1)的符号识别:分子分母中有且只有一个素数,取“+”;分子分母中没有素数或两个都是素数时取“-”。) 1) 求s(2011)(精确到小数点后5位)。

2) 设1<=n<=2011,当n为多大时,s(n)最大。 3) 设1<=n<=2011,当n为多大时,s(n)最接近0。 2. 设计要点

在求和之前应用“试商判别法”对第k个奇数2k-1是否为素数进行标注: 若2k-1为素数,标注a[k]=1; 否则,若2k-1不是素数,a[k]=0。

设置k循环(1——n),循环中分别情况求和:

若a[k]+a[k+1]=1,即(2k-1)与(2k+1)中有且只有一个素数,实施“+”;

否则,若a[k]+a[k+1]!=0,即(2k-1)与(2k+1)中没有素数或有两个素数,实施“-”。 同时,设置最大变量smax,最接近“0”的绝对值变量mi。

在循环中,每计算一个和值s,与smax比较确定最大值,同时记录此时的项数k1; 因s可正可负,s的绝对值与mi比较确定最接近“0”的绝对值,记录此时的项数k2,同时记录此时的和值s2。

最后,求和循环结束时输出所求值。 3. 程序实现

// 基于素数的分数和

14

#include #include

void main()

{ int t,j,n,k,k1,k2,a[3000]; double s,s2,smax,mi;

printf(\请输入整数n: \

scanf(\

for(k=1;k<=n+1;k++) a[k]=0; for(k=2;k<=n+1;k++)

{for(t=0,j=3;j<=sqrt(2*k-1);j+=2)

if((2*k-1)%j==0) {t=1;break;}

if(t==0) a[k]=1; // 标记第k个奇数2k-1为素数 }

s=0;smax=0;mi=10; for(k=1;k<=n;k++)

{if(a[k]+a[k+1]==1) // 判断a[k]与a[k+1]中有一个素数 s+=(double)(2*k-1)/(2*k+1); // 实施加 else

s-=(double)(2*k-1)/(2*k+1); // 否则,实施减 if(s>smax)

{smax=s;k1=k;} // 比较求最大值smax if(fabs(s)

{mi=fabs(s);k2=k;s2=s;} // 绝对值比较求最接近0点 }

printf(\

printf(\当k=%d时s有最大值: %.5f\\n\printf(\当k=%d时s=%.5f最接近0. \\n\}

4. 程序运行示例 请输入整数n: 2011 s(2011)=-211.88387

当k=387时s有最大值: 35.88835 当k=785时s=-0.04341最接近0.

2.5.2 整数的因数比

1. 案例提出

设整数a的小于其本身的因数之和为s,定义

15

p(a)=s/a 为整数a的因数比。

事实上,a为完全数时,p(a)=1。

有些资料还介绍了因数之和为数本身2倍的整数,如p(120)=2。 试求指定区间[x,y]中整数的因数比最大值。 2. 设计要点

设置max存储因数比最大值。穷举区间内每一整数a,求得其因数和s。通过s/a与max比较求取因数比最大值。

对比较得因数比最大的整数,通过试商输出其因数和式。 3. 程序实现

// 求[x,y]范围内整数的因数比最大值 #include #include void main()

{ double a,s,a1,s1,b,k,t,x,y,max=0;

printf(\求区间[x,y]中整数的因数比最大值.\ printf(\请输入整数x,y:\

scanf(\

for(a=x;a<=y;a++) // 穷举区间内的所有整数a {s=1;b=sqrt(a);

for(k=2;k<=b;k++) // 试商寻求a的因数k if(fmod(a,k)==0)

s=s+k+a/k; // k与a/k是a的因数,求和 if(a==b*b)

s=s-b; // 如果a=b^2,去掉重复因数b t=s/a; if(max

printf(\整数%.0f的因数比最大:%.4f \\n\ printf(\的因数和为:\\n\

printf(\输出其因数和式 for(k=2;k<=a1/2;k++) if(fmod(a1,k)==0)

printf(\}

(3) 程序运行示例

求区间[x,y]中整数的因数比最大值.请输入整数x,y: 1,2011 整数1680的因数比最大:2.5429

16