第一周
题解
1. [洛谷P8682] 等差数列
1-1. 题干
![](https://i-blog.csdnimg.cn/blog_migrate/8cccfc6fc0145ca26459f7b78d3ecfe3.png)
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. 题干
![](https://i-blog.csdnimg.cn/blog_migrate/73b37de13080fa1126a4f8b290d036aa.png)
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. 题干
![](https://i-blog.csdnimg.cn/blog_migrate/f66129051d44d1a107757f0c6acc4b5a.png)
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. 题干
![](https://i-blog.csdnimg.cn/blog_migrate/46175cbfc405345f3761054a317c613e.png)
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;
}