紫皮java_紫皮书 - 第2章 循环结构程序设计

第二章 循环结构程序设计

2.1 for循环

例题:

输出1,2,3\(\cdots\) \(\cdots\) n的值

程序2-1

#include

using namespace std;

int main()

{

int n;

cin>>n;

for(int i=0;i<=n;i++)

cout<

return 0;

}

提示:尽量缩短变量的定义范围,避免在其他地方调用而修改内容。

[ ] 一次循环后变量内定义的变量就会被释放。

例题2-1 aabb

输出形如aabb的4位完全平方数(即前两位数字相等,后两位数字也相等)。

程序2-2

#include

#include

using namespace std;

int main()

{

for(int a=1;a<=9;a++)

for(int b=0;b<=9;b++)

{

int n=a*1100+b*11; //在这里使用n,因此在这里定义

int m=floor(sqrt(n)+0.5); /* 函数floor(x)返回不超过x的最大整数

这里不能写成if(sqrt(n)==floor(sqrt(n))),浮 点数计算会产生误差

一般改成四舍五入,即floor(x+0.5) */

if(m*m==n)

cout<

}

return 0;

}

[ ] floor(x)等于1的区间为[1,2),floor(x+0.5)等于1的区间为[0.5,1.5)

程序2-3

#include

using namespace std;

int main()

{

for(int i=1;;i++)

{

int n=i*i;

if(n<1000) continue;

if(n>9999) break;

int hi=n/100;

int lo=n%100;

if(hi/10==hi%10 && lo/10==lo%10)

cout<

}

return 0;

}

[ ] 比较2和3程序,2是先组成aabb形式,然后判断是否为完全平方数;3则是先组成完全平方数,然后判断是否是aabb形式。2在开根号时容易产生误差,而枚举平方根法可以避免开平方的操作。

2.2 while循环和do-while循环

例题2-2 3n+1问题

对于任意大于1的自然数\(n\),若\(n\)为奇数,则将\(n\)变为3\(n\)+\(1\),否则变为\(n\)的一半。输入\(n\),输出变换的次数。

\(n\) $\leq$109。经过若干次这样的变换,一定会使n变为1。

程序2-4

#include

using namespace std;

int main()

{

long n; //当n过大时,很容易乘法溢出,要将n设为长整型。

int count=0; //count是用来充当计数器的变量

cin>>n;

while(n>1)

{

if(n%2==1) n=n*3+1;

else n/=2;

/*

cout<

*/

count++;

}

cout<

return 0;

}

例题2-3 近似计算

计算\(\frac{\pi}{4}\) =1-\(\frac{1}{3}\)+\(\frac{1}{5}\)-\(\frac{1}{7}\)+\(\cdots\) \(\cdots\),直到最后一项小于10-6。

【分析】因为在计算完一项之后才知道它是否小于10-6,所以循环终止是在计算之后,这时候就适合用do-while循环。

程序2-5

#include

#include

using namespace std;

int main()

{

double sum=0;

for(int i=0; ;i++)

{

double term=1.0/(2*i+1);

if(i%2==0) sum+=term;

else sum-=term;

if(term<1e-6) break;

}

cout<

return 0;

}

程序2-6

#include

#include

using namespace std;

int main()

{

double sum=0;

double term;

int i=0;

do

{

term=1.0/(2*i+1);

if(i%2==0)

sum+=term;

else

sum-=term;

i++;

//cout<

}while(term>1e-6);

cout<

return 0;

}

2.3 循环的代价

例题2-4 阶乘之和

输入 \(n\),计算 \(S=1!+2!+3!+\cdots+n!\) 的末六位(不含前导0)。\(n\)$\leq\(10^6^,\)n$$!$表示前 \(n\)个正整数之积。

程序2-7

#include

using namespace std;

#include

int main()

{

const int MOD=1000000;

int n,s=0;

cin>>n;

for(int i=1;i<=n;i++)

{

int f=1;

for(int j=1;j<=i;j++)

f=(f*j%MOD); //在每步计算之后对n取余,结果不变。

s=(s+f)%MOD;

//cout<25之后六位不变,因为25!后六位为零

}

cout<

cout<

return 0;

}

提示:可以使用time.h和clock()函数获得程序的运行时间。常数CLOCKS_PER_SEC和操作系统相关,请不要直接直接使用clock()的返回值,而应总是除以CLOCKS_PRE_SEC。

2.4算法竞赛中的输入输出框架

提示:在Windows下输入完毕后先按Enter键,再按Ctrl+Z键,最后再按Enter键,即可结束输入。在Linux下,输入完毕后按Ctrl+D键即可结束输入。

提示:变量在未赋值之前的值是不确定的。特别的,他不一定等于0。

[ ] 几乎所有算法竞赛的输入数据和标准答案都是保存在文件中的。

使用输入输出重定向,只需在main函数的入口处加入一下两条语句:

freopen("input.txt","r",stdin);

freopen("output.txt","w",stdout);

程序2-8 (重定向版)

#include

using namespace std;

#define LOCAL

#define INF 1000000000

int main()

{

#ifdef LOCAL

freopen("data.in","r",stdin); //重定向的部分写在了#ifdef和#endif中

freopen("data.out","w",stdout);

#endif

int x,n=0,min=INF,max=-INF,s=0;

cin>>x;

while(x!=0)

{

s+=x;

if(x

if(x>max) max=x;

/*

cout<

*/

n++;

cin>>x;

}

cout<

return 0;

}

程序2-9 (fopen版)

#include

#define INF 1000000000

int main()

{

FILE *fin,*fout;

fin=fopen("data.in","rb");

fout=fopen("data.out","wb");

int x,n=0,min=INF,max=-INF,s=0;

while(fscanf(fin,"%d",&x)==1)

{

s+=x;

if(x

if(x>max) max=x;

n++;

}

fprinf(fout,"%d%d%.3f\n",min,max,(double)s/n);

fclose(fin);

fclose(fout);

return 0;

}

知识点:

[ ] 先声明变量fin和fout,把scanf改成fscanf,第一个参数为fin;把printf改成fprintf,第一个参数为fout,最后执行fclose,关闭两个文件。

[ ] 如果想把fopen版的程序改写成标准输入输出,只需赋值"fin=stdin;fout=stdout"即可。

2.5注解与习题

习题1 水仙花数

输出100~999中的所有水仙花数。若3位数ABC满足\(ABC\)=\(A\)3+\(B\)3+\(C\)3,则称其为水仙花数。

#include

using namespace std;

int main()

{

//int a,b,c;

for(int i=100;i<=999;i++)

{

int a=i%10;

int b=i/10%10;

int c=i/100;

if(i==a*a*a+b*b*b+c*c*c)

cout<

}

return 0;

}

习题2 韩信点兵

韩信点兵每次让队伍以三人一队,五人一队,七人一队,只要看队尾的人数就可以知道总人数,总人数不超过一百。输入包含多组数据,每组数据包含3个非负整数 \(a\) , \(b\) , \(c\) ,表示每种队形排尾的人数( \(a\) ❤️, \(b\) <5, \(c\) <7),输出总人数的最小值(或报告无解)。已知总人数不小于10,不超过100。输入到文件结束为止。

#include

using namespace std;

int main()

{

int x,y,z; //定义最后一排的人数

int n;

while(cin>>x>>y>>z)

{

for(n=10;n<=101;n++)

{

if(n==101)

{

cout<

break;

}

if(n%3==x && n%5==y && n%7==z)

{

cout<

break;

}

}

}

return 0;

}

习题3 倒三角

输入正整数n<=20,输出一个n层的倒三角形。

#########

#######

​ #####

​ ###

​ #

#include

using namespace std;

int main()

{

int n;

cin>>n;

for(int i=1;i<=n;i++)

{

for(int j=1;j

cout<

for(int k=2*(n-i)+1;k>=1;k--)

cout<

cout<

}

return 0;

}

习题4 子序列的和

输入两个正整数\(n\)

#include

using namespace std;

int main()

{

long long n,m; //当输入n,m较大时,容易溢出

double sum=0.0;

while(cin>>n>>m)

{

double sum=0.0;

for(long long i=n;i<=m;i++)

sum+=1.0/(i*i);

cout<

}

return 0;

}

习题5 分数化小数

输入正整数\(a\), \(b\), \(c\); 输出\(a\) / \(b\)的小数形式,精确到小数点后 \(c\) 位。\(a\), \(b\) $\leq$106, \(c\)$\leq$100。输入包含多组数据,结束标记为a=b=c=0。

#include

using namespace std;

#include

int main()

{

double a,b,c;

while(cin>>a>>b>>c)

{

cout<

}

return 0;

}

习题6 排列

用1,2,3 \(\cdots\) \(\cdots\) 9组成3个三位数\(abc\), \(def\) , \(ghi\) 。每个数字恰好用一次,要求 \(abc\) : \(def\) : \(ghi\)=1:2:3。

#include

using namespace std;

int add=0,mul=1;

void return13(int num)

{

int x,y,z;

x=num/100;

y=num/10%10;

z=num%10;

add+=x+y+z; //计算三位数字的和

mul*=x*y*z; //计算三位数字的乘积

}

int main()

{

for(int i=123;i<=329;i++)

{

int j=i*2;

int k=i*3;

return13(i);

return13(j);

return13(k);

if(add==45&&mul==362880) //1~9的和为45,9!=362880

cout<

add=0;

mul=1;

}

return 0;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值