算法竞赛入门经典(第二版)第二章



一、例题2-1 aabb

输出所有形如aabb的4位完全平方数(即前两位数字相等,后两位数字也相等)
完全平方数:完全平方即用一个整数乘以自己例如11,22,3*3等等,依此类推。若一个数能表示成某个整数的平方的形式,则称这个数为完全平方数。

代码一
#define _CRT_SECURE_NO_WARNING
#pragma warning(disable : 4996)
#include<stdio.h>
#include<math.h>
int main()
{
    for(int a=1;a<=9;a++)
        for (int b = 0; b <= 9; b++) {
           int n = a * 1100 + b * 11;//这里才开始使用n,因此在这里定义n
           int m = floor(sqrt(n) + 0.5);//floor向下取整函数
            if (m*m==n)printf("%d\n", n);
        }
    return 0;
}

floor函数相关知识
假设在经过大量计算后,由于误差的影响,整数1变成了0.9999999999,floor的结果会 是0而不是1。为了减小误差的影响,一般改成四舍五入,即floor(x+0.5)(2)。如果难以理 解,可以想象成在数轴上把一个单位区间往左移动0.5个单位的距离。floor(x)等于1的区间 为[1,2),而floor(x+0.5)等于1的区间为[0.5,1.5)。


代码二

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

#define _CRT_SECURE_NO_WARNING
#pragma warning(disable : 4996)
#include<stdio.h>
#include<math.h>
int main()
{
    for(int i=1;;i++)
    {
        int n = i * i;
        if (n < 1000)continue;
        if (n > 9999)break;
        int h = n / 100;
        int l = n % 100;
        if ((h/10==n%10) && (l/10==l%10))printf("%d\n", n);
        }
    return 0;
}

这段代码运行没结果,可能有bug
这里的continue语句的作用是排除不足四位数的n,直接检查后面的数。当然,也可以直 接从x=32开始枚举,但是continue可以帮助我们偷懒:不必求出循环的起始点。有了break, 连循环终点也不必指定——当n超过9999后会自动退出循环。

二、程序2-5 3n+1问题

猜想(4):对于任意大于1的自然数n,若n为奇数,则将n变为3n+1,否则变为n的一半。 经过若干次这样的变换,一定会使n变为1。例如,3→10→5→16→8→4→2→1。 输入n,输出变换的次数。n≤10^9。
样例输入:
3
样例输出:
7

#define _CRT_SECURE_NO_WARNING
#pragma warning(disable : 4996)
#include<stdio.h>
#include<math.h>
int main()
{
    int n1,c=0;
    scanf("%d", &n1);
    long long n = n1;//成功算出n= 987654321时的答案为180。
    while (n < 10 ^ 9 && n!=1)//先判断再执行
    {
        if (n % 2 != 0)n = 3 * n + 1;
        else n /= 2;
        c++;
    }
    printf("%d", c);
    return 0;
}

三、例题2-3 近似计算

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

代码一
#define _CRT_SECURE_NO_WARNING
#pragma warning(disable : 4996)
#include<stdio.h>
#include<math.h>
int main()
{
    int i = 1,j=1;
    double s = 0;
    do {//先执行再判断
        s = s + j * 1.0 / i;
        j = -j;
        i += 2;

    } while (1.0 / i >=1e-6);  
    printf("%.2f", s);
    return 0;
}


四、例题2-4 阶乘之和

输入n,计算S=1!+2!+3!+…+n!的末6位(不含前导0)。n≤106,n!表示 前n个正整数之积。
样例输入:
10
样例输出:
37913

#define _CRT_SECURE_NO_WARNING
#pragma warning(disable : 4996)
#include<stdio.h>
#include<math.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 *= j;
        s =(s+factorial)%MOD;
    }
    printf("%d\n", s);
    printf("Time used=%.2f\n", (double)clock() / CLOCKS_PER_SEC);//计时后发现效率很慢
    return 0;
}

总结

后续仍需再补充

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值