上海市计算机学会2022年11月丙组解题报告
文章目录
奇偶数的判定
题目描述
给定一个整数 n n n,若 n n n 是一个偶数,输出 even,若 n n n 是一个奇数,输出 odd。
输入格式
单个整数:表示 n n n。
输出格式
单个字符串:表示 n n n 的奇偶性
数据范围
∘ − 1 , 000 , 000 ≤ n ≤ 1 , 000 , 000 \circ -1,000,000\leq n\leq 1,000,000 ∘−1,000,000≤n≤1,000,000
样例数据
输入:
0
输出:
even
输入:
-1
输出:
odd
思路
直接模2判断即可
代码
#include <bits/stdc++.h>
using namespace std;
int main(){
int n;
cin >> n;
if(n % 2)
cout << "odd" << endl;
else
cout << "even" << endl;
return 0;
}
搭积木
题目描述
小爱同学想要用积木搭起一个金字塔。为了结构稳定,金字塔的每一层要比上一层多一块积木。即搭建规则如下:
金字塔的第 1 1 1 层需要放 1 1 1 块积木
金字塔的第 2 2 2 层需要放 2 2 2 块积木
金字塔的第 3 3 3 层需要放 3 3 3 块积木
…
金字塔的第 i i i 层需要放 i i i 块积木
现在小爱拿到了 n n n 块积木,请问他最高可以搭出多少层的金字塔?
输入格式
输入一个正整数 n n n,表示小爱手中的积木数量
输出格式
输出一个正整数,表示小爱最高能搭的金字塔层数
数据范围
∘
\circ
∘ 对于
50
%
50\%
50% 的数据,
1
≤
n
≤
1
,
000
1 \leq n \leq 1,000
1≤n≤1,000
∘
\circ
∘ 对于
100
%
100\%
100% 的数据,
1
≤
n
≤
1
,
000
,
000
,
000
1 \leq n \leq 1,000,000,000
1≤n≤1,000,000,000
样例数据
输入:
12
输出:
4
说明:
4层金字塔需要1+2+3+4=10块积木,而5层金字塔需要1+2+3+4+5=15块积木,所以小爱在有12块积木的情况下,最多搭4层金字塔
思路
while循环将n从1开始减去即可
代码
#include <bits/stdc++.h>
using namespace std;
int main(){
int n;
cin >> n;
int p = 1;
while(n >= p){
n -= p;
p++;
}
cout << p - 1 << endl;
return 0;
}
最长平台
题目描述
给定一个整数数列 a 1 , a 2 , … , a n a_1 , a_2 , \dots, a_n a1,a2,…,an,请找出最长平台,并输出最长平台的数量(数字相等但位置不同的平台算作不同的平台)。
所谓平台,就是指数列中一段连续的、完全相等的数字,单个数字可以成为一个平台。
输入格式
第一行:单个整数
n
n
n
第二行:
n
n
n个整数
a
1
,
a
2
,
…
,
a
n
a_1 , a_2 , \dots, a_n
a1,a2,…,an
输出格式
两个整数:表示最长平台的长度与最长平台的数量
数据范围
∘
\circ
∘ 对于
50
%
50\%
50% 的数据,
n
≤
1000
n\leq 1000
n≤1000
∘
\circ
∘ 对于
100
%
100\%
100% 的数据,
n
≤
500
,
000
n\leq 500,000
n≤500,000
∘
\circ
∘
1
≤
a
i
≤
1
,
000
,
000
1\leq a_i\leq 1,000,000
1≤ai≤1,000,000
样例数据
输入:
7
2 2 2 1 3 3 3
输出:
3 2
说明:
最长平台为2 2 2或3 3 3
输入:
5
3 1 4 1 5
输出:
1 5
说明:
每个数字单独成一个平台
思路
直接将数组从1~n扫一边,用map映射连续平台的数目
输出最长平台及map映射的内容
代码
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 5e5 + 10;
int n , a[MAXN];
map <int , int> mp;
int main(){
cin >> n;
for(int i = 1; i <= n; ++i)
cin >> a[i];
int ansmax = 1 , p = 1;
for(int i = 1; i < n; ++i){
if(a[i + 1] == a[i])
p++;
else{
mp[p]++;
ansmax = max(ansmax , p);
p = 1;
}
}
mp[p]++;
ansmax = max(ansmax , p);
cout << ansmax << " " << mp[ansmax] << endl;
return 0;
}
积木染色
题目描述
有 n n n 块积木排成一排,小爱需要给每块积木染色,颜色有 m m m 种,请问有多少种方法,能使相邻两块积木的颜色均不相同?
输入格式
输入两个正整数 n , m n , m n,m
输出格式
输出满足条件的方案数模 1 0 9 + 7 10^9 +7 109+7 的结果
数据范围
∘
\circ
∘ 对于
30
%
30\%
30% 的数据,
1
≤
n
,
m
≤
10
1 \leq n,m \leq 10
1≤n,m≤10
∘
\circ
∘ 对于
60
%
60\%
60% 的数据,
1
≤
n
,
m
≤
1
0
4
1 \leq n,m \leq 10^4
1≤n,m≤104
∘
\circ
∘ 对于
100
%
100\%
100% 的数据,
1
≤
n
≤
1
0
15
,
1
≤
m
≤
1
0
9
1 \leq n \leq 10^{15},1 \leq m \leq 10^9
1≤n≤1015,1≤m≤109
样例数据
输入:
3 2
输出:
2
说明:
合法的染色方案有:{1,2,1} {2,1,2}
思路
简单的排列组合,已知第一个积木有 m m m个选择方法,因为相邻方块颜色不相同,则第二个积木有 m − 1 m - 1 m−1种选法,第三种也有 m − 1 m - 1 m−1种选法,以此类推,则结果为 m ( m − 1 ) n − 1 m(m - 1)^{n-1} m(m−1)n−1(类似有两条上衣和三条裤子,结果为 2 ∗ 3 2*3 2∗3一样),但由于 n n n的数据量过大,则需要快速幂取模解决
代码
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const ll MOD = 1e9 + 7;
ll n , m;
ll fpow(ll a, ll b) {
ll re = 1;
while(b > 0){
if (b & 1)
re = re * a % MOD;
b >>= 1;
a = (a * a) % MOD;
}
return re % MOD;
}
int main(){
cin >> n >> m;
ll ans = m;
ans = ans * fpow(m - 1 , n - 1);
cout << ans % MOD << endl;
return 0;
}
出栈序列
题目描述
给定一个长度为 n n n 的、仅由小写字母组成的字符串,将其按序依次放入栈中。
请问在所有可能的出栈序列中,字典序最小的出栈序列是多少?
输入格式
输入第一行, 一个正整数
n
n
n
输入第二行,一个长度为
n
n
n 的字符串
输出格式
输出所有出栈序列中,字典序最小的出栈序列
数据范围
∘
\circ
∘ 对于
30
%
30\%
30% 的数据,
1
≤
n
≤
10
1 \leq n \leq 10
1≤n≤10
∘
\circ
∘ 对于
60
%
60\%
60% 的数据,
1
≤
n
≤
1
0
3
1 \leq n \leq 10^3
1≤n≤103
∘
\circ
∘ 对于
100
%
100\%
100% 的数据,
1
≤
n
≤
1
0
5
1 \leq n \leq 10^5
1≤n≤105
样例数据
输入:
3
yes
输出:
esy
说明:
字符y、e、s依次进栈,所有出栈的可能性有:
{yes}、{yse}、{eys}、{esy}、{sey}
其中 {esy} 的字典序最小
思路
易想到输出结果中一定是先输出字典序最小,所以从输入的字符串中找字典序最小的字母,维护后缀最小字典序的值
然后依次从字符串中判断是否是现在及后面的最小字典序值,若是则输出,否则压入栈中
若现在后缀最小值等于现在的字符并且后面仍然有相同的字符也应该输出,现在的字符是可判断的,而在后面中无法确定下一个字符的值
代码
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1E5 + 10;
string s;
int n;
char a[MAXN];
int main(){
cin >> n >> s;
a[n - 1] = s[n - 1];
for (int i = n - 2; i >= 0; --i)
a[i] = min(s[i], a[i + 1]);
stack<char>stk;
stk.push(s[0]);
int inc = 1;
while (!stk.empty() || inc < n){
if (stk.empty() || inc < n && stk.top() > a[inc]){
stk.push(s[inc++]);
} else{
cout << stk.top();
stk.pop();
}
}
cout << endl;
return 0;
}