ACM算法学习-第一周

第一周

题解

1. [洛谷P8682] 等差数列

1-1. 题干
1-2. 解析
  • 求N个整数构成的等差数列项数, 求出其 最大值 , 最小值公差 即可, 其中 公差 需要在每相邻的两项的最大公约数中取取出最小值, 才能包含输入的所有元素
  • 解题思路:
    • 输入数据
    • sort排序
    • 循环取两两公约数并保留最大值
    • 利用最大, 最小值计算项数

p.s. 所有项均相等的数列也属于等差数列

1-3. 原码
#include <iostream>
#include <algorithm>
using namespace std;
int num[100010];

int main()
{
    int n;
    cin >> n;
    for (int i = 0; i < n; i++)
    {
        cin >> num[i];
    }
    sort(num, num + n);
    int x = num[1] - num[0];
    if(x == 0)
    {
        cout << n;
        return 0;
    }
    for (int i = 1; i < n - 1; i++)
    {
        x = __gcd(x, num[i] - num[i - 1]);
    }
    int result = (num[n - 1] - num[0]) / x + 1;
    cout<< result << endl;
    return 0;
}

2. [洛谷P1226]【模板】快速幂

2-1. 题干
2-2. 解析
  • 求a的b次 并对其 求余 , 因b过大不能直接将b个a相乘, 需要根据b的奇偶对求幂过程进行简化, 并在计算过程中求余防止溢出
  • 解题思路:
    • 完成函数-判断奇偶并简化求幂过程
    • 输入数据
    • 使用函数并求余
2-3. 原码
#include<iostream>
using namespace std;
long long a, b, p;
long long divide(long long a, long long b)
{
    if(b == 0)
    {
        return 1;
    }
    else if(b == 1)
    {
        return a;
    }
    else if(b % 2 == 0)
    {
        return divide((a % p) * (a % p), b / 2) % p;
    }
    else
    {
        return a % p * divide((a % p) * (a % p), (b - 1) / 2) % p;
    }
}

int main()
{
    cin >> a >> b >> p;
    long long i = b, s = 0;
    s = divide(a, b) % p;
    cout << a << "^"
         << b << " mod "
         << p << "="
         << s << endl;
    return 0;
}

3. [洛谷P2249]【深基13.例1】查找

3-1. 题干
3-2. 解析
  • 在数列中搜索元素, 在数列较大的情况下循环搜索是不可行的,需要使用 二分法 ——在一定的范围中取中间值进行判断,再通过修改上下限以指数级的速度缩小范围
  • 解题思路:
    • 输入数据
    • 设置数列第一项以及最后一项的下标作为初始范围
    • 将中间项与需查找的数值进行循环比较,“>=” 则使中间项为下限, “<” 则使其为上限, 上下限间无整数则跳出循环, 此时上限+1
    • 若查找的结果存在, 上限所在值应为第一个出现的该结果, 输出, 否则输出 “-1”
3-3. 原码
#include<iostream>
using namespace std;
int a[1000010];

int main()
{
    int n, m;
    cin >> n >> m;
    for (int i = 0; i < n; i++)
    {
        cin >> a[i];
    }
    while (m--)
    {
        int num;
        cin >> num;
        int first = 0, last = n - 1;
        while(first < last)
        {
            int mid = 0;
            mid = (first + last) / 2;
            if(a[mid] >= num)
            {
                last = mid;
            }
            else
            {
                first = mid + 1;
            }
        }
        if(a[first] == num)
        {
            cout << (first + 1) << " ";
        }
        else
        {
            cout << "-1 "; 
        }
    }
    return 0;
}

4. [洛谷P1824] 进击的奶牛

4-1. 题干
4-2. 解析
  • 二分法最小值的最大值, 对 最小距离值 进行二分, 并通过函数判断是否可行, 最终在最小距离值可行的方案中选择最大值
  • 解题思路:
    • 完成判断函数——以第一牛棚作为初始起点, 循环计算各牛棚到其的距离, 一旦该距离大于距离最小值, 该方案可容纳的牛数量+1, 起点改为当前牛棚. 循环结束后若可容纳的牛数量大于题设数量C, 则该方案可行
    • 输入数据
    • 对牛棚位置数组进行排序
    • 设置0为上限, 第一到最后牛棚距离为下限, 进行二分. 此时中值为最小距离值
    • 将中值代入函数进行判断,true 则使中间项为上限并记录该值, false 则使其为下限, 上下限间无整数则跳出循环
    • 输出循环结束前的最后一个符合要求的最小距离值, 该值则为最小值的最大值
4-3. 原码
#include <iostream>
#include <algorithm>
using namespace std;
int num[100010];
int n, c;

bool judge(int mid)
{
    int bullnum = 1;
    int first = num[0];
    for (int i = 1; i < n; i++)
    {
        if (num[i] - first >= mid)
        {
            bullnum++;
            first = num[i];
        }
    }
    if (bullnum >= c)
    {
        return true;
    }
    else
    {
        return false;
    }
}

int main()
{
    cin >> n >> c;
    for (int i = 0; i < n; i++)
    {
        cin >> num[i];
    }
    sort(num, num + n);

    int first = 0, last = num[n - 1] - num[0], max = 0;
    while (first + 1 < last)
    {
        int mid = (first + last) / 2;
        if (judge(mid))
        {
            first = mid;
            max = mid;
        }
        else
        {
            last = mid;
        }
    }
    cout << max << endl;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值