本文主要是介绍【三】【算法分析与设计】第三届程序设计竞赛部分题目,竖式加法,竖式乘法,求序列差最大,小红的字符串,再编号,消灭飞龙,世界五子棋,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
竖式加法
链接:登录—专业IT笔试面试备考平台_牛客网 来源:牛客网
题目描述
小红对简单的加法很在行。
她想知道对于一个正整数A,她需要找到一个最小的正整数B,以确保A+B会产生进位。
输入描述:
输入共 T+1 行。
第一行一个整数表示 T组数据(1≤T≤10^5)
接下来T行,每行一个整数表示A(1≤A≤10^8)
输出描述:
输出共T行,表示最小的正整数B
示例1
输入
3
114514
1314520
100
输出
6
80
900
备注:
T(1≤T≤10^5)
A(1≤A≤10^8)
#include <iostream> // 包含标准输入输出库
#include <math.h> // 包含数学库
using namespace std;int main() {int n; // 定义变量n表示数据组数long long nums; // 定义变量nums表示输入的正整数Aint count; // 定义变量count用于记录A末尾有多少个连续的0cin >> n; // 输入数据组数nfor (int i = 1; i <= n; i++) { // 遍历每组数据cin >> nums; // 输入正整数Acount = 0; // 初始化count为0while (1) { // 循环判断A末尾的连续0if (nums % 10 == 0) { // 如果A末尾是0count++; // 计数器加1nums = nums / 10; // A除以10,去掉末尾的0} else {break; // 如果A末尾不是0,跳出循环}}int num = nums % 10; // 取A的最后一位非0数字// 计算最小的正整数B使得A+B产生进位,结果为(10 - num)乘以10的count次方cout << (int)((10 - num) * pow(10, count)) << endl; // 输出结果}
}
int、long、longlong的范围
int
-
最小范围是 $$-2^{31}$$ 到 $$2^{31}-1$$。
-
这可以近似表示为 $$-2.1 \times 10^9$$到 $$2.1 \times 10^9$$。
-
所以,对于
int
,使用 $$10^9$$。
long
-
对于32位系统,
long
的范围与int
相同,即 $$-2.1 \times 10^9$$ 到 $$-2.1 \times 10^9$$,或 $$10^9$$。 -
对于64位系统,
long
的最小范围是 $$-2^{63}$$ 到 $$2^{63}-1$$,近似为 $$-9.2 \times 10^{18}$$ 到 $$9.2 \times 10^{18}$$。 -
所以,对于
long
,在64位系统上使用 $$10^{18}$$。
long long
-
long long
的范围至少是 $$-2^{63}$$ 到 $$2^{63}-1$$,近似表示为 $$-9.2 \times 10^{18}$$ 到 $$9.2 \times 10^{18}$$。 -
因此,对于
long long
,也是使用 $$10^{18}$$。
总结:
-
int: $$10^9$$
-
long (32位系统): $$10^9$$
-
long (64位系统) 和 long long: $$10^{18}$$
竖式乘法
链接:登录—专业IT笔试面试备考平台_牛客网 来源:牛客网
题目描述
今天,小红参加了数学课,老师教授了竖式乘法的计算方法。但是,由于小红上课时分神,只听懂了一部分。在小红看来,他对两个整数a和b的竖式乘法进行了如下的计算,例如有a =123,b=321
123
*321
-----
123
246
369
-----
738
现在,小红给出了a和b,希望你按照小红的竖式乘法计算一下它们的乘积。
输入描述:
第一行为一个t,表示有t组数据
接下来有t行,每行为a,b。
输出描述:
输出为t行,每行为一组答案。
示例1
输入
3
123 321
111 111
100 12
输出
738
333
300
备注:
1≤t≤10^3,
1≤a,b≤10^9
#include <iostream> // 包含标准输入输出库
using namespace std;int main() {int n; // 定义变量n表示数据组数long long a, b; // 定义变量a和b表示两个整数cin >> n; // 输入数据组数nfor (int i = 1; i <= n; i++) { // 遍历每组数据cin >> a >> b; // 输入两个整数a和blong long sum = 0; // 初始化sum为0,用于存储竖式乘法的结果while (1) { // 循环进行竖式乘法的计算if (b != 0) { // 如果b不等于0sum += (b % 10) * a; // 取b的最后一位与a相乘,并累加到sumb = b / 10; // b除以10,去掉最后一位} else { // 如果b等于0break; // 跳出循环}}cout << sum << endl; // 输出竖式乘法的结果}
}
求序列差最大
链接:登录—专业IT笔试面试备考平台_牛客网 来源:牛客网
题目描述
给出一个长度为n的序列a,定义bi为a1~ai中的最大值,ci为a1~ai中的最小值。
现在你可以将序列a重新排列,要求最大化
并输出这个最大的值。
输入描述:
第一行输入一个正整数n (1≤n≤10^5)
接下来一行 m个正整数表示序列a(1≤ai≤10^9)
输出描述:
输出一行一个整数,表示重排序列 a 后
的最大值。
示例1
输入
5
1 2 3 4 5
输出
16
示例2
输入
3
4 8 1
输出
14
备注:
n(1≤n≤10^5)
a(1≤ai≤10^9)
#include <iostream>
#include <vector>
#include<limits.h>
using namespace std;
int main() {int n;cin >> n;long long max = INT_MIN, min = INT_MAX;vector<int> a(n);for (auto& x : a) {cin >> x;if (x > max) max = x;if (x < min) min = x;}cout << (max - min)*(n - 1) << endl;}
小红的字符串
链接:登录—专业IT笔试面试备考平台_牛客网 来源:牛客网
题目描述
小明收到了小红赠送的一个全由小写英文字母构成的字符串,但小明认为这个字符串看起来不够美观。
在小明看来,一个美观的字符串应当保证任何相邻的字符都不相同。他想知道,要将这个字符串转换成一个美观的字符串,至少需要添加多少个字符。
你只需告诉他,添加最少字符后的字符串长度是多少。
输入描述:
第一行一个数T(1≤T≤10)
接下来T行,每行一个有且仅有小写英文字母构成的字符串s(1≤|s|≤100000)
输出描述:
输出T行,每行一个数,表示美化后串的最短长度
示例1
输入
4
a
ab
abbc
aaabb
输出
1
2
5
8
备注:
1≤T≤10
1≤|s|≤100000
#include <iostream> // 包含标准输入输出库
#include <vector> // 包含向量库
#include <limits.h> // 包含INT_MIN和INT_MAX定义
using namespace std;int main() {int n; // 定义变量n表示序列长度cin >> n; // 输入序列长度nlong long max = INT_MIN, min = INT_MAX; // 初始化最大值max为最小整数,最小值min为最大整数vector<int> a(n); // 定义长度为n的向量afor (auto& x : a) { // 遍历向量a中的每个元素cin >> x; // 输入序列中的每个元素if (x > max) max = x; // 更新最大值maxif (x < min) min = x; // 更新最小值min}cout << (max - min) * (n - 1) << endl; // 计算并输出结果(max - min) * (n - 1)
}
再编号
链接:登录—专业IT笔试面试备考平台_牛客网 来源:牛客网
题目描述
有一群人,每个人都有一个独特的标识编号ai。
再编号对于每个人的编号a是一种操作,记为a',满足
。
现在有一系列询问,共m次。每次询问给定一对x和t,表示经过t次再编号后,我们需要知道第x个人的新编号是多少。
由于结果可能非常大,因此我们需要对10^9+7取模。
输入描述:
第一行2个数n,m,表示人数和询问次数
接下来一行n个数,表示ai
接下来m行,每行2个数x,t,描述一次询问。
输出描述:
m行,第i行1个数表示第i次询问的答案对10^9+7取模的结果。
示例1
输入
4 3
1 2 3 4
1 0
2 2
4 1
输出
1
22
6
备注:
n ≤ 100000 , m ≤ 10000 , t ≤ 100000 , 1 ≤ a(i) ≤ 1000000000
#include <iostream> // 包含标准输入输出库
#include <vector> // 包含向量库
#include <limits.h> // 包含INT_MIN和INT_MAX定义
#include <numeric> // 包含标准库函数
#include <math.h> // 包含数学库using namespace std;int main() {const long long mod = 1e9 + 7; // 定义常量mod为10^9 + 7vector<long long> coefficient(100010); // 定义大小为100010的向量coefficient用于存储系数long long sum = 0; // 初始化sum为0,用于存储所有ai的和long n, m; // 定义变量n表示人数,m表示询问次数cin >> n >> m; // 输入人数和询问次数vector<long long> a(n); // 定义大小为n的向量a用于存储每个人的标识编号for (auto &x : a) { // 遍历向量a中的每个元素cin >> x; // 输入每个人的标识编号sum = (sum + x % mod) % mod; // 更新sum,计算所有标识编号的和并对mod取模}// 计算并存储系数coefficientfor (int i = 1, j = 1; i <= 100010; i++) { // 遍历从1到100010coefficient[i] = (j - coefficient[i - 1] + mod) % mod; // 计算当前系数并对mod取模j = j * (n - 1) % mod; // 更新j为j乘以(n-1)并对mod取模}// 处理每次询问for (int i = 1; i <= m; i++) { // 遍历每次询问long x, t; // 定义变量x表示第x个人,t表示t次再编号cin >> x >> t; // 输入x和tlong long ans = sum * coefficient[t]; // 计算初始答案ans为sum乘以coefficient[t]if (t % 2 == 0) { // 如果t是偶数cout << (ans + a[x-1] + mod) % mod << endl; // 输出结果(ans + a[x-1] + mod)对mod取模} else { // 如果t是奇数cout << (ans - a[x-1] + mod) % mod << endl; // 输出结果(ans - a[x-1] + mod)对mod取模}}
}
消灭飞龙
链接:登录—专业IT笔试面试备考平台_牛客网 来源:牛客网
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
凯丽面对着一群共n只飞龙,它们排成一列,每只飞龙站在一个位置上。
她的攻击可以同时命中连续3个位置上的飞龙(也可以只击中一只,或者是相邻两只),每次攻击造成一点伤害。
当一只飞龙的血量降至零时,该飞龙被视为被消灭(但位置仍然保留)。
此外,她还拥有一个魔法,可以在战斗的任意时刻使用,但只能使用一次,能够直接消灭相邻的2个位置上的飞龙(即使只有一只飞龙也可以使用,位置仍然保留)。
请问,她最少需要发动多少次攻击,才能消灭所有飞龙?
因为她已经力竭,所以需要你这个聪明的朋友来帮帮她!
输入描述:
第一行一个数n,分别表示飞龙的数量
第二行共n个整数,第i个整数表示ai,表示第i只飞龙的血量
输出描述:
共一个数,表示需要挥出的斩击数
示例1
输入
复制10 3 2 2 2 3 1 1 2 1 2
10
3 2 2 2 3 1 1 2 1 2
输出
复制5
5
说明
对1,2使用魔法,接下来的斩击位置为:
3 4 5
3 4 5
5 6 7
8 9 10
8 9 10
备注:
1 ≤n≤10^6,0≤ai≤10^9
1.
定义前缀和dp1[i],表示消灭a数组[0~i]位置的飞龙需要的最少的斩击数,并且此时维护a数组中飞龙的剩余生命值。
定义前缀和dp2[i],表示消灭a数组[i~n-1]位置的飞龙需要的最少的斩击数,并且此时维护a数组中飞龙的剩余生命值。
2.
枚举所有需要用药水的位置,对于每一个位置计算需要的最少的斩击数是多少,统计所有情况的最小值。
3.
void mincut1(vector<LL>& dp, int left, int right, vector<LL> a) { //a[left,right]
计算前缀和数组dp1,left到right位置的状态值。实际上left==1,right==n。
a数组中0位置没有飞龙,飞龙从1~n位置。
4.
dp[left - 1] = 0;
初始化0位置的值,状态转移方程是dp[i]=dp[i-1]+a[i]。
意思是花费最小斩击数消灭0~i-1位置飞龙,并且维护完a[i],a[i+1]的剩余生命值,此时花费最小斩击数消灭0~i位置飞龙的斩击数是多少。
是花费最小斩击数消灭消灭0~i-1位置飞龙加上i位置飞龙剩余的生命值,并维护后面的飞龙剩余生命值。
因此dp[0]=0。
5.
for (int i = left; i <= right; i++) {
dp[i] = dp[i - 1] + a[i];
此时说明砍了i,i+1,i+2位置飞龙a[i]次,看完之后维护i+1,i+2位置飞龙的剩余生命值。
if(i+1<=right) a[i + 1] = a[i + 1] - a[i] > 0 ? a[i + 1] - a[i] : 0;
if(i+2<=right) a[i + 2] = a[i + 2] - a[i] > 0 ? a[i + 2] - a[i] : 0;
}
}
6.
计算前缀和dp2,同理可得。
void mincut2(vector<LL>& dp, int left, int right, vector<LL> a) { //a[left,right]
dp[right + 1] = 0;
for (int i = right; i >= left; i--) {
dp[i] = dp[i + 1] + a[i];
if(i-1>=left) a[i - 1] = a[i - 1] - a[i] > 0 ? a[i - 1] - a[i] : 0;
if(i-2>=left) a[i - 2] = a[i - 2] - a[i] > 0 ? a[i - 2] - a[i] : 0;
}
}
7.
枚举用魔法的所有可能位置位置。
for (int i = 1; i <= n; i++) { // [1,i-1][i,i+1][i+2,n]
sum = min(sum, (i - 1 >= 1 ? dp1[i - 1] : 0) + (i + 2 <= n ? dp2[i + 2] : 0));
}
#include <iostream> // 包含标准输入输出库
using namespace std;
#include <vector> // 包含向量库
#include <climits> // 包含INT_MIN和INT_MAX定义
using LL = long long; // 定义LL为long long的别名// 计算前缀和数组dp1,表示从left到right位置飞龙的最小斩击数
void mincut1(vector<LL>& dp, int left, int right, vector<LL> a) {dp[left - 1] = 0; // 初始化dp[left - 1]为0for (int i = left; i <= right; i++) { // 遍历从left到right的每个位置dp[i] = dp[i - 1] + a[i]; // 计算dp[i]为dp[i - 1]加上a[i]的值if (i + 1 <= right) a[i + 1] = a[i + 1] - a[i] > 0 ? a[i + 1] - a[i] : 0; // 更新i+1位置飞龙的剩余生命值if (i + 2 <= right) a[i + 2] = a[i + 2] - a[i] > 0 ? a[i + 2] - a[i] : 0; // 更新i+2位置飞龙的剩余生命值}
}// 计算前缀和数组dp2,表示从right到left位置飞龙的最小斩击数
void mincut2(vector<LL>& dp, int left, int right, vector<LL> a) {dp[right + 1] = 0; // 初始化dp[right + 1]为0for (int i = right; i >= left; i--) { // 遍历从right到left的每个位置dp[i] = dp[i + 1] + a[i]; // 计算dp[i]为dp[i + 1]加上a[i]的值if (i - 1 >= left) a[i - 1] = a[i - 1] - a[i] > 0 ? a[i - 1] - a[i] : 0; // 更新i-1位置飞龙的剩余生命值if (i - 2 >= left) a[i - 2] = a[i - 2] - a[i] > 0 ? a[i - 2] - a[i] : 0; // 更新i-2位置飞龙的剩余生命值}
}int main() {int n; // 定义变量n表示飞龙的数量cin >> n; // 输入飞龙的数量vector<LL> a(n + 3); // 定义大小为n+3的向量a,用于存储每只飞龙的血量vector<LL> dp1(n + 3); // 定义大小为n+3的向量dp1,用于存储前缀和vector<LL> dp2(n + 3); // 定义大小为n+3的向量dp2,用于存储前缀和for (int i = 1; i <= n; i++) { // 遍历每只飞龙cin >> a[i]; // 输入每只飞龙的血量}LL sum = LONG_LONG_MAX; // 初始化sum为long long类型的最大值if (n >= 3) { // 如果飞龙数量大于等于3mincut1(dp1, 1, n, a); // 调用mincut1函数计算dp1mincut2(dp2, 1, n, a); // 调用mincut2函数计算dp2} else if (n == 1 || n == 2) { // 如果飞龙数量为1或2cout << 0 << endl; // 输出0return 0; // 结束程序}for (int i = 1; i <= n; i++) { // 遍历每个位置// 计算sum为用药水消灭飞龙的最小斩击数sum = min(sum, (i - 1 >= 1 ? dp1[i - 1] : 0) + (i + 2 <= n ? dp2[i + 2] : 0));}cout << sum << endl; // 输出最小斩击数return 0; // 结束程序
}
世界五子棋
链接:登录—专业IT笔试面试备考平台_牛客网 来源:牛客网
题目描述
艾米最近沉迷于世界五子棋,她在棋盘上放了一些棋子。 世界五子棋的规则如下。
给定一个n*m的棋盘。棋盘上有两种棋子“1”和“2”,其中每种棋子分别计算得分。
假如相同种类的五个棋子连成相邻的一行,一列,或斜对角线的情况,每有五个这样的棋子,该种类棋子加1分。
艾米已经把她的棋子都摆在了棋盘上。
但是艾米并不太聪明的样子,她希望你,聪明的朋友,告诉她,她两种棋子的得分。
输入描述:
第一行两个整数n,m,表示棋盘的大小。
接下来输入一个n*m的矩阵,表示棋盘。
“1”,“2”表示该位置有对应的棋子。
“0”表示该位置没有棋子。
输出描述:
一行2个整数,以空格隔开,表示“1”,“2”两种棋子各自的得分。
示例1
输入
20 20
10202022021000221222
22111122221221101010
11211001210010001210
02222120211010112111
21220011111022120012
00111101111212221010
22122012211221212111
22102022221121110211
20222121122221221121
10012221102212201222
12110201221022101111
02212201100112112111
22111222202221211110
12112222222122102121
21021120121212010221
10222001121022022112
11111201112100221021
12112102021200111100
21021021011222222202
12021221122012111212
输出
10 12
备注:
1<=n,m<=1000
#include <iostream> // 包含标准输入输出库
#include <vector> // 包含向量库
using namespace std;// 检查是否有连续的五个相同的棋子
bool checkFive(const vector<vector<int>>& board, int x, int y, int dx, int dy) {int count = 1; // 计数器,初始化为1int n = board.size(), m = board[0].size(); // 获取棋盘的行数和列数int cur = board[x][y]; // 当前棋子的类型for (int i = 1; i < 5; ++i) { // 检查接下来的四个位置int nx = x + i * dx; // 计算新位置的行int ny = y + i * dy; // 计算新位置的列if (nx >= n || ny >= m || ny < 0 || board[nx][ny] != cur) return false; // 如果越界或棋子类型不同,返回falsecount++; // 计数器加1}return count == 5; // 如果计数器等于5,返回true
}// 主函数
int main() {int n, m; // 定义变量n和m表示棋盘的大小cin >> n >> m; // 输入棋盘的大小vector<vector<int>> board(n, vector<int>(m)); // 定义棋盘,大小为n*mvector<int> score(3, 0); // 定义得分数组,分别存储0, 1, 2的得分,实际上0不会被使用// 读入棋盘数据for (int i = 0; i < n; ++i) { // 遍历棋盘的每一行for (int j = 0; j < m; ++j) { // 遍历棋盘的每一列char ch; // 定义字符变量chcin >> ch; // 输入字符board[i][j] = ch - '0'; // 将字符转换为整数并存储在棋盘中}}// 遍历棋盘for (int i = 0; i < n; ++i) { // 遍历棋盘的每一行for (int j = 0; j < m; ++j) { // 遍历棋盘的每一列if (board[i][j] == 0) continue; // 如果是空位,跳过// 检查四个方向if (j + 4 < m && checkFive(board, i, j, 0, 1)) score[board[i][j]]++; // 水平方向if (i + 4 < n && checkFive(board, i, j, 1, 0)) score[board[i][j]]++; // 垂直方向if (i + 4 < n && j + 4 < m && checkFive(board, i, j, 1, 1)) score[board[i][j]]++; // 主对角线方向if (i + 4 < n && j - 4 >= 0 && checkFive(board, i, j, 1, -1)) score[board[i][j]]++; // 副对角线方向}}// 输出结果cout << score[1] << " " << score[2] << endl; // 输出1号和2号棋子的得分return 0; // 返回0,程序结束
}
结尾
最后,感谢您阅读我的文章,希望这些内容能够对您有所启发和帮助。如果您有任何问题或想要分享您的观点,请随时在评论区留言。
同时,不要忘记订阅我的博客以获取更多有趣的内容。在未来的文章中,我将继续探讨这个话题的不同方面,为您呈现更多深度和见解。
谢谢您的支持,期待与您在下一篇文章中再次相遇!
这篇关于【三】【算法分析与设计】第三届程序设计竞赛部分题目,竖式加法,竖式乘法,求序列差最大,小红的字符串,再编号,消灭飞龙,世界五子棋的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!