第一节 for语句 (计数循环)
(一)格式:
注意:分号的位置格式。
(二)语句格式举例:
(1)将控制变量从1变到100,增量为 1 for(i=1;i<=100;++i)
(2)将控制变量从100变到1,增量为 -1 for(i=100;i>=1;--i)
(3)控制变量从7变到77, 增量为 7 for(i=7;i<=77;i+=7)
(4)for(int i=20; i>=2;i-=2) 控制变量从20变到2,增量为-2
(5)for(int j=99; j>=0; j-=11) 按数列改变控制变量值:99、88、77、 66、55、44、33、22、11、0,增量为-11
(6)for(int i=1, j=2; i<=99&&j<=100; i+=2,j+=2) 控制变量i和j共同进行循环控制,i从1变到99, j从2变到100,增量都为2。
(三)执行流程图:
首先执行表达式1(初始表达式)。如果表达式2(条件表达式)的值为非0,就重复执行循环体内的语句和表达式3(递增或递减表达式),直到表达式2(条件表达式)的值为0时止。
(四)例题分析:
例4.1 输出1—100之间所有偶数。
#include<bits/stdc++.h>
using namespace std;
int main ()
{ for (int i=2; i<=100 ; i+=2)
cout << i << " ";
return 0;
}
例4.2 利用for循环,计算输出1+2+…+100的和 。
#include<bits/stdc++.h>
using namespace std;
int main ()
{ int sum=0;
for (int i=1; i<=100 ; ++i)
sum+=i;
cout<<sum;
return 0;
}
例4.3 利用for循环计算n!的值。分析:n!=1*2*3…*n 。
#include<bits/stdc++.h>
using namespace std;
int main ()
{ long long s; //因为阶乘是一个很大的数,存放阶乘的变量要大一点;
int i,n; //n不能定义为long long,否则for语句死循环
s=1;
scanf("%d",&n);
for (int i=1; i<=n ; ++i)
s*=i; //若s定义为int,当n=13时s的值就溢出了
printf("%lld\n",s); //低版本也可用printf("%l64d\n",s)
return 0;
}
【说明】:
当n>=13时,s值超过了int类型的表示范围。还有一种比int更大的类型,称为long long,它的表示范围是 -2 ^63~2^63-1,比-10^19~10^19略窄,而我们一直使用的int范围是-2^31~2^31-1,只比-2*10^9~2*10^9略宽。
输入输出long long也可以借助于printf和scanf语句,但对应的占位符却是和平台与编译器相关的:
在linux中,gcc很统一的用%lld;在windows中,MinGW的gcc和VC6可用%I64d;高版本编译器下windows可以使用%lld。
例4.4 利用for循环,分别计算1—100中奇数的和、偶数的和。
#include<bits/stdc++.h>
using namespace std;
int main()
{ int jssum=0;
int ossum=0;
for (int js=1,os=2;js<=99&&os<=100;js+=2 ,os+=2 )
{ jssum+=js; ossum+=os; }
cout <<"the sum of odd numbers 1 to 100 is : "<<jssum<<endl;
cout <<"the sum of even numbers 1 to 100 is :"<<ossum<<endl;
return 0;
}
例5: 输入‘A’到‘Z’中的任一个字符,输出如下回文串。如:输入‘B’,则输出ABA;输入‘E’,则输出ABCDEDCBA。
分析:该回文串可以分为两个部分 ,如输入为‘E’时,分为ABCDE和DCBA两部分。可以用两个循环语句,循环变量可以先从‘A’循环到 ‘E’,再从‘D’循环到‘A’。
#include<bits/stdc++.h>
using namespace std;
int main()
{ char c,ci;
printf("输入一个大写字母\n");
c=getchar( );
for(ci='A';ci<=c;ci++) printf("%c",ci);
ci--; ci--;
for( ;ci>='A';ci--) printf("%c",ci);
printf("\n");
}
(五)for语句 计数循环 上机练习:
1、输出1—100之间所有偶数。
2、利用for循环,计算输出1+2+…+100的和。
3 、利用for循环计算n!的值。分析:n!=1*2*3…*n 。
4 、利用for循环,分别计算1—100中奇数的和、偶数的和。
5、输入‘A’到‘Z’中的任一个字符,输出如下回文串。
如: 输入‘B’,则输出ABA;输入‘E’,则输出 ABCDEDCBA。
6、将一根长为369cm的钢管截成长为69cm和39cm两种规格的短料。在这两种规格的短料到少各截一根的前提下如何截才能余料最少。
7、一个两位数x,将它的个位数字与十位数字对调后得到一个新数y,此时y恰好比x大36,请编程求出所有这样的两位数。
8、把整数3025从中剪开分为30和25两个数,此时再将这两数之和平方,(30+25)^2=3025计算结果又等于原数。求所有符合这样条件的四位数。
9、已知一对兔子,每个月可以生一对小兔,而小兔经过一个月生长后也可每月生一对小兔。即兔子的对数是:第一个月1对,第二个月2对,第三个月3对,第四个月5对,…,假设兔子的生育期是12个月,并且不死,问一年后,这对兔子有多少对活着的后代?
10、猴子摘了一堆桃子,第一天吃了一半,觉得不过隐又吃了一个;第 二天吃了剩下的一半零一个;以后每天如些,到第十天,猴子一看只剩下 一个了。问最初有多少个桃子。
第二节 while语句 (当循环)
(一)格式:
格式一:只要表达式的值为非0,就重复语句, 直到表达式值为0时止
格式二:只要表达式的值为非0,就重复执行大括号中的复合语句, 直到表达式值为0时止
注意:分号的书写。括号及大括号后都没有分号。
(二)格式举例:
(1) i=0;
while (i<10) ++i;
功能:当 i 的值小于10,重复执行 ++i 语句
(2) cin>>x;
while(x<0) cin>>x;
功能:当输入的数据小于0时,重复读数据。
(三)流程图及语句执行过程
(1)计算作为循环控制条件表达式的值,得到逻辑真或假,。
(2)若表达式为真,则执行了一遍循环体,
(3)若表达式为假,离开循环,结束整个while语句的执行。
(4)循环体的所有语句执行结束后,自动转向第(1)步执行。
(四)例题分析:
例4.5 求s=1 +2 +3……+n,当加到第几项时,s的值会超过1000?
#include<bits/stdc++.h>
using namespace std;
int main()
{ int n=0,s=0;
while (s<=1000)
{ ++n;
s+=n;
}
cout<<n;
return 0;
}
例4.6 求两个正整数m,n的最大公约数。
#include<bits/stdc++.h>
using namespace std;
int main ()
{ int m,n,r;
cin>>m>>n;
r =m % n;
while (r!=0)
{ //也可以使用 while (r),c++中 非0即真
m=n;
n=r;
r=m % n;
}
cout<<"最大公约数="<<n<<endl;
return 0;
}
分析:求两个整数的最大公约数可以采用辗转相除法。
以下是辗转相除法的算法:分别用m,n,r表示被除数、除数、余数;
1、求m除以n的余数r;
2、当r!=0,执行第3步;若r==0,则n为最大公约数,算法结束。
3、将n的值赋给m,将r的值赋给n;再求m除以n的余数r。
4、转到第2步
例4.7 编一程序求满足不等式1+ 1/2 + 1/3 …+1/n >=5的最小n值。
#include<bits/stdc++.h>
using namespace std;
int main ()
{ int i=0;
float s=0;
while(s<5) //当s的值还未超过5时
{ ++i;
s+=1.0/i;
}
cout<<i;
return 0;
}
分析:
此题不等式的左边是一个求和的算式,该和式中的数据项个数是未知的,也正是要求出的。对于和式中的每个数据项,对应的通式为1/i,i=1,2,…n。 所以可采用循环累加的方法来计算出它的值。
设循环变量为i,它应从1开始取值,每次增加1,直到和式的值不小于5为止,此时的i值就是所求的n。设累加变量为s,在循环体内把1/i的值累加到s上。
若采用for循环来写,则如下所示:
#include<bits/stdc++.h>
using namespace std;
int main ()
{
int i;
float s=0;
for(i=1;s<5;++i)
s+=1.0/i;
cout<<i-1;
return 0;
}
例4.8 数据统计
输入一些整数,求出它们的最小值、最大值和平均值(保留3位小数)。输入保证这些数都是不超过1000的整数。
样例输入:2 8 3 5 1 7 3 6
样例输出:1 8 4.375
#include<bits/stdc++.h>
using namespace std;
int main()
{ int x,n=0,min=10000,max=-10000,s=0;
while (scanf("%d",&x)==1)
{ s+=x;
if (x<min) min=x;
if (x>max) max=x;
++n;
}
printf("%d %d %.3lf\n",min,max,(double)s/n);
return 0;
}
Scanf()函数与printf()返回值
一、 scanf 函数是有返回值的,它的返回值可以分成三种情况:
1、 返回正整数,表示正确输入参数个数。 如执行 scanf(“%d %d”, &a, &b);
如果输入“3 4”,可以正确输入,返回2(正确输入了两个变量);
如果输入“3,4”,可以正确输入a,无法输入b,返回1 (只正确输入一个变量)
2、返回0,表示用户的输入不匹配,没有输入任何值。如执行 scanf(“%d %d”, &a, &b);
如果输入“ , 3 4”,开始是逗号,没有输入任何值则返回0。
3、返回EOF(EOF是在stdio.h里面定义的常量,值为-1)表示输入流已经结束。
在Windows下,用户按下CTRL+Z(会看到一个^Z字符)再按下回车,就表示输入结束;
在Linux/Unix下使用CTRL+D表示输入结束。
二、printf的返回值是输出的字符数,
例如,printf("1234")的返回值是4,而printf("1234\n")的返回值是5。
(五)while语句 当循环 上机练习:
1.球弹跳高度的计算【1.5编程基础之循环控制17】
一个球从某一高度h落下(单位米),每次落地后反跳回原来高度的一半,再落下。 编程计算气球在第10次落地时,共经过多少米? 第10次反弹多高?
输出包含两行,第1行:到球第10次落地时,一共经过的米数。第2行:第10次弹跳的高度。
输入: 输入一个整数h,表示球的初始高度。
输出: 第1行:到球第10次落地时,一共经过的米数。
第2行:第10次弹跳的高度。
注意:结果可能是实数,结果用double类型保存。
提示:输出时不需要对精度特殊控制,用cout << ANSWER,或者printf("%g", ANSWER)即可。
样例输入: 20
样例输出: 59.9219
0.0195313
2.角谷猜想【1.5编程基础之循环控制18】
所谓角谷猜想,是指对于任意一个正整数,如果是奇数,则乘3加1,如果是偶数,则除以2,得到的结果再按照上述规则重复处理,最终总能够得到1。
如,假定初始整数为5,计算过程分别为16、8、4、2、1。
程序要求输入一个整数,将经过处理得到1的过程输出来。
输入: 一个正整数N(N <= 2,000,000)
输出: 从输入整数到1的步骤,每一步为一行,每一部中描述计算过程。最后一行输出"End"。如果输入为1,直接输出"End"。
样例输入: 5
样例输出: 5*3+1=16
16/2=8
8/2=4
4/2=2
2/2=1
End
3.级数求和【1.5编程基础之循环控制24】Noip2002普及组第1题
已知:Sn= 1+1/2+1/3+…+1/n。显然对于任意一个整数K,当n足够大的时候,Sn大于K。现给出一个整数K(1<=k<=15),要求计算出一个最小的n,使得Sn>K。
输入: 一个整数K。
输出: 一个整数n。
样例输入: 1
样例输出: 2
4.分离整数的各个数【1.5编程基础之循环控制25】
给定一个整数n(1<=n<=100000000),要求从个位开始分离出它的每一位数字。从个位开始按照从低位到高位的顺序依次输出每一位数字。
输入: 输入一个整数,整数在1到100000000之间。
输出: 从个位开始按照从低位到高位的顺序依次输出每一位数字。数字之间以一个空格分开。
样例输入: 123
样例输出: 3 2 1
5.数字反转【1.5编程基础之循环控制26】Noip2011普及组第1题
给定一个整数,请将该数各个位上数字反转得到一个新数。新数也应满足整数的常见形式,即除非给定的原数为零,否则反转后得到的新数的最高位数字不应为零,例如输入-380,反转后得到的新数为-83。
输入: 输入共 1 行,一个整数N。 -1,000,000,000 ≤ N≤ 1,000,000,000。
输出: 输出共 1 行,一个整数,表示反转后的新数。
样例输入: 123
样例输出 321
样例输入: -380
样例输出 -83
6.含k个3的数【1.5编程基础之循环控制27】
输入两个正整数m和k,其中1<m<100000,1<k<5 ,判断m 能否被19整除,且恰好含有k个3,如果满足条件,则输出YES,否则,输出NO。
例如,输入:43833 3,满足条件,输出YES。如果输入:39331 3,尽管有3个3,但不能被19整除,也不满足条件,应输出NO。
输入: m 和 k 的值,中间用单个空格间隔。
输出: 满足条件时输出 YES,不满足时输出 NO。
样例输入: 43833 3
样例输出: YES
第三节 do-while语句 (直到循环)
(一)格式:
格式一: 循环体部分由一条语句构成。
格式二: 循环体部分如果由多个语句构成, 应由一对花括号括起来,构成一个语句块的形式。
注意:分号的书写。括号及大括号后都没有分号。
(二)流程图及执行过程:
语句执行过程 :
(1)执行一遍循环体。
(2)求出作为循环条件的“条件表达式”的值,若为逻辑值真则自动转向第(1)步,否则结束do循环,继续执行循环后面的语句。
注意: 在do语句的循环体中也可以使用break(中断)语句,来非正常结束循环的执行。
(三)例题分析:
例4.10 求1992个1992的乘积的末两位数是多少?
#include<bits/stdc++.h>
using namespace std;
int main()
{ int a=1,t=0;
do
{ ++t;
a=(a*92)%100;
} while (t!=1992);
cout<<a<<endl;
return 0;
}
【分析】
积的个位与十位数只与被乘数与乘数的个位与十位数字有关,所以本题相当于求1992个92相乘,而且本次的乘积是下一次相乘的被乘数,因此也只需取末两位参与运算就可以了。
例4.11 校体操队到操场集合,排成每行2人,最后多出1人;排成每行3人,也多出1人;分别按每行排4,5,6人,都多出1人;当排成每行7人时,正好不多。求校体操队至少多少人?
#include<bits/stdc++.h>
using namespace std;
int main()
{ bool yes;
int x=0;
do
{ yes=true;
x+=7;
if (x%2!=1) yes=false;
if (x%3!=1) yes=false;
if (x%4!=1) yes=false;
if (x%5!=1) yes=false;
if (x%6!=1) yes=false;
}while (yes==false); //直到yes的值为真
cout<<"All="<<x;
return 0;
}
【分析】
①设校体操队为x人,根据题意x应是7的倍数,因此x的初值为7,以后用x+=7)改变x值;
②为了控制循环, 用逻辑变量yes为真(true) 使循环结束;
③如果诸条件中有一个不满足, yes 的值就会为假(false),就继续循环。 程序中对每个x值,都先给yes 赋真值,只有在循环体各句对x进行判断时,都得到“通过”(此处不赋假值)才能保持真值。
(四)while语句 直到循环 上机练习:
1.球弹跳高度的计算【1.5编程基础之循环控制17】
一个球从某一高度h落下(单位米),每次落地后反跳回原来高度的一半,再落下。 编程计算气球在第10次落地时,共经过多少米? 第10次反弹多高?
输出包含两行,第1行:到球第10次落地时,一共经过的米数。第2行:第10次弹跳的高度。
输入: 输入一个整数h,表示球的初始高度。
输出: 第1行:到球第10次落地时,一共经过的米数。
第2行:第10次弹跳的高度。
注意:结果可能是实数,结果用double类型保存。
提示:输出时不需要对精度特殊控制,用cout << ANSWER,或者printf("%g", ANSWER)即可。
样例输入: 20
样例输出: 59.9219
0.0195313
2.角谷猜想【1.5编程基础之循环控制18】
所谓角谷猜想,是指对于任意一个正整数,如果是奇数,则乘3加1,如果是偶数,则除以2,得到的结果再按照上述规则重复处理,最终总能够得到1。
如,假定初始整数为5,计算过程分别为16、8、4、2、1。
程序要求输入一个整数,将经过处理得到1的过程输出来。
输入: 一个正整数N(N <= 2,000,000)
输出: 从输入整数到1的步骤,每一步为一行,每一部中描述计算过程。最后一行输出"End"。如果输入为1,直接输出"End"。
样例输入: 5
样例输出: 5*3+1=16
16/2=8
8/2=4
4/2=2
2/2=1
End
3.级数求和【1.5编程基础之循环控制24】Noip2002普及组第1题
已知:Sn= 1+1/2+1/3+…+1/n。显然对于任意一个整数K,当n足够大的时候,Sn大于K。现给出一个整数K(1<=k<=15),要求计算出一个最小的n,使得Sn>K。
输入: 一个整数K。
输出: 一个整数n。
样例输入: 1
样例输出: 2
4.分离整数的各个数【1.5编程基础之循环控制25】
给定一个整数n(1<=n<=100000000),要求从个位开始分离出它的每一位数字。从个位开始按照从低位到高位的顺序依次输出每一位数字。
输入: 输入一个整数,整数在1到100000000之间。
输出: 从个位开始按照从低位到高位的顺序依次输出每一位数字。数字之间以一个空格分开。
样例输入: 123
样例输出: 3 2 1
5.数字反转【1.5编程基础之循环控制26】Noip2011普及组第1题
给定一个整数,请将该数各个位上数字反转得到一个新数。新数也应满足整数的常见形式,即除非给定的原数为零,否则反转后得到的新数的最高位数字不应为零,例如输入-380,反转后得到的新数为-83。
输入: 输入共 1 行,一个整数N。 -1,000,000,000 ≤ N≤ 1,000,000,000。
输出: 输出共 1 行,一个整数,表示反转后的新数。
样例输入: 123
样例输出 321
样例输入: -380
样例输出 -83
6.含k个3的数【1.5编程基础之循环控制27】
输入两个正整数m和k,其中1<m<100000,1<k<5 ,判断m 能否被19整除,且恰好含有k个3,如果满足条件,则输出YES,否则,输出NO。
例如,输入:43833 3,满足条件,输出YES。如果输入:39331 3,尽管有3个3,但不能被19整除,也不满足条件,应输出NO。
输入: m 和 k 的值,中间用单个空格间隔。
输出: 满足条件时输出 YES,不满足时输出 NO。
样例输入: 43833 3
样例输出: YES
三种循环之间的比较:
同一个问题,往往既可以用 while语句解决,也可以用 do-while或者for语句来解决,但在实际应用中,应根据具体情况来选用不同的循环语句。选用的一般原则是:
(1) 如果循环次数在执行循环体之前就已确定,一般用 for语句。 如果循环次数是由循环体的执行情况确定的,一般用 while语句或者do- while语句。
(2) for和while是先判断条件是否满足,满足条件再执行循环体, do...while循环不管条件是否满足都会执行循环体一次;
(3) C++/C循环语句中,for语句使用频率最高,while语句其次,do语句很少用。
(4) 三种循环语句for、while、do-while可以互相嵌套自由组合。但要注意的是,各循环必须完整,相互之间绝不允许交叉。
(5) 在while循环和do while循环中,只在while后面的括号内指定循环条件,因此为了使循环能正常结束,应该在循环中包含使循环趋于结束的语句(如 i++)。
for循环可以在表达式3中包含使循环趋于结束的语句,甚至可以将循环所有操作放到语句3中。因此for语句的功能更强,凡是while循环能完成的for循环都可以完成。
(6) 在用while循环和do while循环时,循环变量初始化操作应在语句之前完成。for语句可以在表达式1中实现循环变量的初始化。
(7) while for do..while 都可以利用break语句跳出循环,用continue结束本次循环。
第四节 循环嵌套
例4.12 求 S=1!+2!+3!+....+10!
#include<bits/stdc++.h>
using namespace std;
int main ()
{ int t,s;
s=0;
for(int i=1;i<=10;++i)
{ t=1;
for (int j=1;j<=i;++j) //求i!
t*=j;
s+=t; //累加i!
}
cout<<s;
return 0;
}
这个程序是一个for循环的嵌套。这种方法是比较容易想到的,但实际上对于求i!,我们可以根据求出的(i-1)!乘上i即可得到,而无需重新从1再累乘到i。
#include<bits/stdc++.h>
using namespace std;
int main ()
{ int t=1,s=0;
for(int i=1;i<=10;++i)
{ t*=i; //t为上一个数的i-1的阶乘值,再乘以i即为i!
s+=t; //累加i!
}
cout<<s;
return 0;
}
显然第二个程序的效率要比第一个高得多。第一个程序要进行1+2+3+…+10=55次循环,而第二程序进行10次循环。若题目中求的是1!+2!+…+1000!,则两个程序的效率区别更明显。
例4.13 一个炊事员上街采购,用500元钱买了90只鸡,其中母鸡一只15元,公鸡一只10元,小鸡一只5元,正好把钱买完。问母鸡,公鸡,小鸡各买了多少只?
【分析】设母鸡i只,公鸡j只,则小鸡为90-i-j只,则15*i+ 10* j+(90-i-j)*5=500,显然一个方程求两个未知数是不能直接求解。必须组合出所有可能的i,j值,看是否满足条件。这里i的值可以是0到33,j的值可以0到50。源程序如下:
#include<bits/stdc++.h>
using namespace std;
int main ()
{ int k;
for (int i=0;i<=33;++i) //枚举母鸡的数量
for (int j=0;j<=50;++j) //枚举公鸡的数量
{ k=90-i-j;
if (15*i+10*j+k*5==500)
cout<<"母鸡有"<<i<<"只,"<<"公鸡有"<<j<<"只,"<<"小鸡有"<<k<<"只" <<endl;
}
return 0;
}
例4.14 利用for循环语句输出图4-1中的三角形。
#include<bits/stdc++.h>
using namespace std;
int main ()
{ for (int i=1; i<=5; ++i) //控制行数
{ for (int j=1; j<=i; ++j) //输出一行中的*数
cout<<"*";
cout<<endl; //换行
}
return 0;
}
例4.15 求100-999中的水仙花数。若三位数ABC,ABC=A^3+B^3+C^3,则称ABC为水仙花数。例如153,1^3+5^3+3^3=1+125+27=153,则153是水仙花数。
【分析】 根据题意,采用三重循环来求解。由于循环次数一定,用for循环最为简单。程序如下:
#include<bits/stdc++.h>
using namespace std;
int main()
{ for (int a=1; a<=9; ++a)
for (int b=0; b<=9; ++b)
for (int c=0; c<=9; ++c)
{ if (a*a*a+b*b*b+c*c*c==a*100+b*10+c)
cout<<setw(6)<<a*100+b*10+c; //setw函数控制输出场宽
}
return 0;
}
运行结果: 153 370 371 407
例4.16 输出100—200中所有的素数。
分析:我们可对100-200之间的每一个整数进行判断,若它是为素数,则输出。而对于任意整数i,根据素数定义,我们从2开始,到sqrt(i),找i的第一个约数,若找到第一个约数,则i必然不是素数。 程序如下:
#include<bits/stdc++.h>
using namespace std;
using namespace std;
int main ()
{ int x;
for (int i=100;i<=200;++i)
{ x=2;
while(x<=floor(sqrt(i))&&(i%x!=0)) //floor为取整函数,需调用cmath库
x=x+1; //在枚举的范围内并且没有出现约数则继续枚举
if ( x>floor(sqrt(i)))
cout<<i<<"\t";
}
return 0;
}
例4.17 输出所有形如aabb的四位完全平方数(即前两位数字相等,后两位数字也相等)。
【分析】 分支和循环结合在一起时威力特别强大:我们枚举所有可能的aabb,然后判断它们是否为完全平方数。
注意,a的范围是1~9,b可以是0。主程序如下:
#include<bits/stdc++.h>
using namespace std;
int main()
{ int a,b,h,t;
for (a=1; a<=9; a++)
for (b=0; b<=9; b++)
{ t=a*1000+a*100+b*10+b;
h=sqrt(t);
if (t==h*h) printf("%d%d%d%d\n",a,a,b,b);
}
}
另一个思路是枚举平方根x,
参考程序如下:
#include<bits/stdc++.h>
using namespace std;
int main()
{ int n=0,hi,lo;
for (int x=1 ; ; ++x)
{//可以直接从x=32开始枚举
n=x*x;
if (n<1000) continue;
if (n>9999) break;
hi = n/100;
lo = n%100;
if (hi/10 == hi%10 && lo/10 == lo%10) printf("%d\n",n);
}
return 0;
}
例4.18 阶乘之和
输入n,计算S=1! + 2! + 3! + … + n!的末6位(不含前导0)。n<=106, n!表示前n个正整数之积。
样例输入:10
样例输出:37913
【分析】 这个任务并不难,引入累加变量S之后,核心算法只有一句话:for (i=1;i<=n;i++) S+=i!。不过C++语言并没有阶乘运算符,所以这句话只是伪代码,而不是真正的代码。事实上,我们还需要一次循环来计算i!:for (j=1;j<=i;++j) factorial*=j;。 注意累乘器factorial(英文“阶乘”的意思)定义在循环里面。换句话说,每执行一次循环体,都要重新声明一次factorial,并初始化为1(想一想,为什么不是0)。因为只要末6位,所以输出时对10^6取模。
#include<bits/stdc++.h>
using namespace std;
int main()
{ int n,s=0;
scanf("%d",&n);
for (int i=1;i<=n;++i)
{ int factorial=1;
for (int j=1;j<=i;++j)
factorial*=j;
s+=factorial;
}
printf("%d\n",s%1000000);
return 0;
}
当n=100时,输出-961703,直觉告诉我们:乘法溢出了。这个直觉很容易通过“输出中间变量”法得到验证,但若要解决这个问题,还需要一点数学知识。试一下n=10^6时输出什么?更会溢出,但是重点不在这里。事实上,它的速度太慢!让我们把程序改成“每步取模”的形式,然后加一个“计时器”,看看它到底有多慢。
#include<bits/stdc++.h>
using namespace std;
int main()
{ const int MOD=1000000;
int n,s=0;
scanf("%d",&n);
for (int i=1;i<=n;++i)
{ int factorial=1;
for (int j=1;j<=i;++j)
factorial=(factorial*j%MOD);
s=(s+factorial)%MOD;
}
printf("%d\n",s);
printf("Time used= %.2lf\n",(double)clock()/CLOCKS_PER_SEC);
return 0;
}
这个程序真正的特别之处在于计时函数clock()的使用。该函数返回程序目前为止运行的时间。这样,在程序结束之前调用它,便可获得整个程序的运行时间。这个时间除以常数CLOCKS_PER_SEC之后得到的值以“秒”为单位。
(二)循环综合 上机练习:
1、编写程序“我与计算机玩猜数游戏”。要求:计算机随机产生大于10,小于1000的商品的价格,你猜数。计算机给出相应的提示信息,大了提示“你猜贵了”,小了提示“太便宜了”。如果在规定10次内猜对,显示“You are clever! ”,否则显示“Sorry!You have no choice”。
2、试编写一个根据随机产生两个操作数和随机产生一个运算符,由计算机输出运算结果的程序。这里只考虑加(+)、减(-)、乘(*)、除(/)四种运算。
3、答题游戏:计算机随机出题,你答题,并给出相应提示。两个操作数均为两位数,运算符为+、-、*、/,答对输出:You are so clever.答错输出:Sorry 样例输出格式如下:14+32=? 46 You are so clever
4、根据参数,画出矩形。
输入:输入一行,包括四个参数:前两个参数为整数,依次代表矩形的高和宽(高不少于3行不多于10行,宽不少于5列不多于10列);第三个参数是一个字符,表示用来画图的矩形符号;第四个参数为1或0,0代表空心,1代表实心。
输出:输出画出的图形。
样例输入: 7 7 @ 0
样例输出:
5、输出九九乘法表。
6、输出以下图形,要求行数、字符都能变化。
7、输出字母塔。
9、四个学生上地理课时,回答我国四大淡水湖的大小时这样说, 甲:最大洞庭湖,最小洪泽湖,鄱阳湖第三; 乙:最大洪泽湖,最小洞庭湖,鄱阳湖第二,太湖第三; 丙:最小洪泽湖,洞庭湖第三; 丁:最大鄱阳湖,最小太湖,洪泽湖第二,洞庭湖第三; 对于每个湖的大小,每个学生仅答对了一个,请编程确定四个湖的大小。
10、有1、2、3、4个数字,能组成多少个互不相同且无重复数字的四位数?都是多少?
11、警察局抓了A 、B、C、D四名偷窃嫌疑犯,其中有一个是小偷。审问A说:“我不是小偷。”B说“C是小偷。”C说:“小偷肯定是D。”D说:“C在冤枉人。”现在已经知道四个人中三人说的是真话,一人说的是假话,问到底谁是小偷?
12、将100元钱兑换成50元、20元、10元的小钞票,有多少种方案,输出每一种 兑换方案。 输出格式:
方案数 | 50元 | 20元 | 10元 |
1 | 0 | 0 | 10 |
2 | 0 | 1 | 8 |
3 | 1 | 2 | 1 |
13、求100~999中的水仙花数。
14、求出e的值【1.5编程基础之循环控制32】
利用公式e = 1 + 1/1! + 1/2! + 1/3! + ... + 1/n! ,求e的值,要求保留小数点后10位。
输入: 输入只有一行,该行包含一个整数n(2<=n<=15),表示计算e时累加到1/n!。
输出: 输出只有一行,该行包含计算出来的e的值,要求打印小数点后10位。
样例输入: 10
样例输出: 2.7182818011
15、阶乘之和
输入n,计算S=1! + 2! + 3! + … + n!的末6位(不含前导0)。n<=106, n!表示前n个正整数之积。
样例输入:10
样例输出:37913
16、任给一个自然数n,求出这个自然数不同因数的个数。如:n=6时,因 为1、2、3、6都是6的因数,故输出为total=4。
17、求2-1000中的亲密数对(如果a的因子和等于b,b的因子和等于a,且a、b不相等,则称ab为亲密对数)。
18、一辆快车和一辆慢车开往同一地点,快车票价为18元,慢车票价为13. 5元,共售出400张,共计5940元,求快车票和慢车票各多少张?.
19、一个正整数,如果它能被7整除,或者它的十进制表示法中某一位上的数字为7,则称其为与7相关的数.现求所有小于等于n(n < 100)的与7无关的正整数的平方和.
20、给定一个十进制正整数n,写下从1到n的所有整数,然后数一下其中出现的数字“1”的个数。 例如当n=2时,写下1,2。这样只出现了1个“1”;当n=12时,写下1,2,3,4,5,6,7,8,9,10,11,12。这样出现了5个“1”。
21、已知正整数 n 是两个不同的质数的乘积,试求出较大的那个质数。
22、把一个合数分解成若干个质因数的乘积的形式,叫做分解质因数。分解质因数只针对合数。
输入样例:36
输出样例:36=2*2*3*3
23、求2~100中每个数的质因数。输出如下:
24、 输出100—200中所有的素数。 分析:我们可对100-200之间的每一个整数进行判断,若它是为素数,则输出。而对于任意整数i,根据素数定义,我们从2开始,到sqrt(i),找i的第一个约数,若找到第一个约数,则i必然不是素数。 程序如下: