当前位置: 首页 > news >正文

算法基础(思想)

 ACM多组数据的处理、求最大公约数的欧几里得算法、快速幂运算,以及求解循环节等问题

一、输入

问题:输入不说明有多少个Input Block

1.EOF为结束标志

EOF是-1

因为scanf返回值是成功读取数据的个数

此例子中,scanf返回的是2;2!=-1,因此while执行

当所有的数都读取完了,scanf返回-1,while结束

C语言:

#include <stdio.h>
int main()
{
    int a, b;
    while (scanf("%d %d", &a, &b) != EOF)
        printf("%d\n", a + b);
    return 0;
}

C++:

while(cin >> a >> b)
{
     ......

}

2. 判断是否等于读取的个数

由scanf的含义,直接判断个数

#include <stdio.h>
int main()
{
    int a, b;
    while (scanf("%d %d", &a, &b) == 2)
        printf("%d\n", a + b);
    return 0;
}

问题:输入不说明有多少个Input Block,但以某个特殊输入为结束标志 

推荐用 if 语句

#include <stdio.h>
int main()
{
    int a, b;
    while (scanf("%d%d", &a, &b) == 2)
    {
        if (a == 0 && b == 0) break;
        printf("%d\n", a + b);
    }
    return 0;
}

问题:输入一整行字符串

C语言(不推荐使用 `gets`):
 

#include <stdio.h>

int main()

{
    char buf[20];
    gets(buf); // 不推荐使用,因为存在缓冲区溢出的风险
    printf("%s\n", buf);
    return 0;
}

C++语言示例(推荐使用 `getline`):
 

#include <iostream>
#include <string>
using namespace std;

int main()

{
    string buf;
    getline(cin, buf); // 使用 std::getline 读取字符串
    cout << buf << endl;
    return 0;
}

C++语言示例(使用字符数组):
 

#include <iostream>
using namespace std;

int main()

{
    char buf[255];
    cin.getline(buf, 255); // 使用 cin.getline 读取字符数组
    cout << buf << endl;
    return 0;
}

gets 在C语言中是不安全的,因为它不检查输入的长度,容易导致缓冲区溢出。

在C++中,推荐使用 `std::getline` 或 `cin.getline` 来安全地读取字符串。

二、输出

注意输出空行、空格、无空格的细节。

三、算法做题思想

1.时刻注意数据溢出

给定一个正整数 nn,请计算 2+3+…+n2+3+…+n 的结果,其中 n<50000。

Sample input:
10
Sample output:
55

法一:暴力——循坏——超时

法二:公式——爆int(超过int范围)

解决爆int:1.long long 类型 %lld (64位整数)2.高精度 等


2.转化问题——问题简单化

给定两个正整数,计算这两个数的最小公倍数。
样例输入:

10 14
4 6
样例输出:
70
12

法一:暴力——数据大会超时

法二:公式——lcm(A,B)=A*B/gcd(A,B)

注:公式先乘后除会爆int,因为:乘后可能会超范围  避免爆int:先除后乘

由此,求最小公倍数变为求最大公倍数gcd(A,B)——辗转相除法(欧几里得算法)

辗转相除法:

x是要求的gcd

①10和14都是x的倍数

②把14分为10和4,那么4也是x的倍数

证明:10=ax;14=bx;(10+4)=bx;ax+4=bx;4=(a-b)x;

③求10和14的gcd可以转变为10和4的gcd

以此类推:

int gcd(int da, int xiao)//不用在乎da和xiao的顺序:会交换回来
{
    int temp;
    while (xiao != 0)
    {
        temp = da % xiao;
        da = xiao;
        xiao = temp;
    }
    return da;
}

3.寻找循环节规律

给定一个正整数 N ,请计算 N 个 N 相乘的结果的个位数是多少(1<=N<=1000000000)。

Sample Input  
3  
Sample Output  
7

法一:纯暴力枚举法——超时

法二:微暴力——每次模10再乘N——可能超时

法三:找规律:

每次个位存起来,什么时候循环了就记循环量,然后直接求余。

个位0~9中,0 1 5 6的次方为它本身

每个数的循环节个数不同,有1、2、4个。可以都按4算

有一种Fibonacci数列,定义如下:

F(0) = 7

F(1) = 11,

F(n) = F(n-1) + F(n-2)

给定一个n(n < 1,000,000),请判断F(n)能否被3整除,分别输出yes和no。

 变换: f(n)%3——(F(n-1) + F(n-2))%3——F(n-1)%3 + F(n-2)%3

每个f%3后发现规律:1 2 0 2 2 1 0 1   1 2 0 2 

1 2 0 2 2 1 0 1 为一个循环节

求A^B(A的B次方)的最后三位数表示的整数(1 <= A, B <= 1000000000)

Sample Input  
2 3  
12 6  

Sample Output  
8  
984

法一:暴力

法二:快速幂算法(二分加速)

把123^234=(123^2)^117

递归:

int power(int a, int n)
{
    int ans;
    if(n == 0) ans = 1;    // 结束条件
    else
    {
        ans = power(a * a, n / 2);    // 递归调用
        if(n % 2 == 1) ans *= a;    // n为奇数
    }
    return ans;
}

循环:

int power(int a, int n)
{
    int ans = 1;
    while (n)
    {
        if (n % 2) ans = ans * a; // 奇数情况
        a = a * a; // 底数平方
        n = n / 2; // 指数减半
    }
    return ans;
}

 

相关文章:

  • OSPF | 理论 / 实验
  • 技术成长战略是什么?
  • Windows 主机与安卓设备网线直连配置教程
  • spark
  • RNN中远距离时间步梯度消失问题及解决办法
  • git使用-克隆远程项目、分支管理
  • I2C实践开发 ---【STM32-I2C-HDC1080温湿度采集系统】
  • 期权帮|股指期货中的套期保值如何操作?
  • Redis三剑客解决方案
  • 模板方法模式原理结构以及在Spring源码中的使用。
  • 前端接收后端19位数字参数,精度丢失的问题
  • 二叉树层序遍历的三种情况(总结)
  • ResponseUtil.out 方法分析
  • Golang连接使用SqlCipher
  • android studio 界面启动模拟器无反应——从命令行启动模拟器
  • 一分钟学会JavaScript 变量
  • vxe-table实现动态列
  • 2025年度福建省职业院校技能大赛高职组“信息安全管理与评估”赛项规程
  • [c++]--类和对象
  • 【uniapp*vue3】app/h5 webview通讯方案
  • 中国证券业协会修订发布《证券纠纷调解规则》
  • 外企聊营商|威能集团:公平环境增“暖”意
  • “异常”只停留在医院里,用艺术为“泡泡宝贝”加油
  • 独行侠以1.8%概率获得状元签,NBA原来真的有剧本?
  • 筑牢安全防线、提升应急避难能力水平,5项国家标准发布
  • 沈阳卫健委通报“健康证”办理乱象:涉事医院已被立案查处