循环结构程序设计

FOR

  • 对于for循环,建议尽量缩短变量的定义范围,例如在初始化部分定义循环变量。
for(int i=0;i<10;i++)

aabb(7744)

输出所有形如aabb的4位完全平方数;

#include<stdio.h>
#include<math.h>

int main()
{
    for(int a=1;a<=9;a++)
    {
        for(int b=1;b<=9;b++)
        {
            int n=a*1100+b*11;//这里才开始使用n,因此在这里定义n
            int m=floor(sqrt(n)+0.5);//函数floor(x)返回不超过x的最大整数 
            if(m*m==n) printf("%d\n",n); 
        }
    }   
    return 0;
 } 

函数floor(x)返回不超过x的最大整数 ,理论上乐意直接判断sqrt(n)是否为整数,但是浮点运算可能出现误差,整数1会变成0.9999999999,floor(sqrt(n))的结果可能就是0而不是1了所以改成四舍五入,即floor(sqrt(n)+0.5);

另一个思路是枚举平方根,从而避免开方操作

#include<stdio.h>
int main()
{
    for(int x=1;;x++)
    {
        int n=x*x;
        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) printf("%d\n",n);
    }   
    return 0;
 } 

while & do-while

3n+1问题

猜想:对于任意大于1的自然数n,若n为奇数,则将n变为3n+1,否则变为n的一半。经过若干次这样的变换,一定会使n变为1。
输入n,输出变换的次数;n<10^9

流行的平台中:int都是32位整数-2^31~2^31-1

这道题就要考虑乘法溢出的问题了,n<10^9只比int的上界小一点,3n+1肯定会溢出;
int不够用,可以使用C99中的long long(-2^63~2^63-1),但是long long的输入输出方法有点奇怪(有的用%lld,有的用%I64d),所以遇到long long,常用C++的输入输出流cin cout。

#include<stdio.h>
int main()
{
    int n2,count=0;
    scanf("%d",&n2);
    long long n=n2;
    while(n>1)
    {
        if(n%2==1) n=3*n+1;
        else n/=2;
        count++;
    }
    printf("%d\n",count);   
    return 0;
 } 

循环终止判断是在计算之后,而不是在计算之前,适合使用do-while;

循环的代价

阶乘之和

输入n,计算S=1!+2!+3!+…+n!的末六位(不含前导0)。n<=10^6;

#include<stdio.h>
#include<time.h>
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 = %.2f\n",(double)clock()/CLOCKS_PER_SEC);    
    return 0;
 } 

要计算只包含加减法,乘法的整数表达式除以正整数n的余数,可以在每步计算之后对n取余,结果不变。

计时函数clock()#include<time.h>)返回程序目前为止的运行时间,这个时间除以常数CLOCKS_PER_SEC之后得到的值以“秒”为单位。

循环结构中最常见的两个问题:
1. 算术运算溢出
2. 程序效率低下

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

while(scanf("%d",&x)==1)

scanf的返回值是成功输入的变量数,当输入结束时,scanf函数无法再次读取x,将返回0;
对于scanf的输入格式,空格,tab和回车符都是无关紧要的,所以按enter并不意味着输入的结束。

在windows下,输入完毕后先按enter,再按ctrl+Z键,最后再按enter即可结束输入;

使用文件输入输出

  1. 使用文件最简单的方法是使用输入输出重定向,只需在main函数的入口处加入以下两条语句:
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);

上述语句使得scanf从文件input.txt读入,printf写入文件output.txt.

  1. 文件输入输出(禁止使用重定向)
#include<stdio.h>
#define INF 10000000000

int mian()
{
    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)
    {
        /*循环语句*/
    }
    fprintf(fout, "%d\n",max );
    fclose(fin);
    fclose(fout);
    return 0;
}

如果想把fopen版的程序改成读写标准输入输出,只需赋值
fin=stdin; fout=stdout;即可,不要调用fopen和fclose;

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值