C++语言篇 第四章 循环结构

第一节  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必然不是素数。 程序如下:

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值