概述
上海市计算机学会竞赛 2023.1 丙组月赛
T1 实验日志
题目描述
小爱正在完成一个物理实验,为期
n
n
n天,其中第
i
i
i天,小爱会记录
a
i
a_i
ai 条实验数据在实验日志中。
已知小爱的实验日志每一页最多纪录 m m m条数据,每天做完实验后他都会将日志合上,第二天,他便从第一页开始依次翻页,直到找到第一个有空白位置的页码为止,开始新一天的数据记录。
请问在整个实验过程中,小爱每天为了找到第一个空白位置,需要翻多少页?
输入格式
输入共两行
第一行,两个正整数
n
,
m
n , m
n,m。
第二行,
n
n
n个正整数,表示每天的数据条数。
输出格式
输出共一行, n n n个正整数,分别表示每一天开始实验前,需要翻的页数。
数据范围
对于
30
%
30%
30% 的数据,
1
≤
n
≤
10
1leq nleq 10
1≤n≤10
对于
60
%
60%
60% 的数据,
1
≤
n
≤
1
0
4
1 leq nleq 10^4
1≤n≤104
对于
100
%
100%
100% 的数据,
1
≤
n
≤
1
0
5
1leq nleq 10^5
1≤n≤105
1
≤
m
,
a
i
≤
n
1leq m,a_ileq n
1≤m,ai≤n
样例数据
输入:
4 10
7 8 5 12
输出:
0 0 1 2
说明:
第一天不用翻页
第二天开始前,由于只记了7条,仍是从第一页开始,不用翻页
第三天开始前,共记录了15条,则是从第二页开始,需翻1页
第四天开始前,共记录了20条,由于第二页已写满,则是从第三页开始,需翻2页
思路
直接加上除以一下页数输出即可
代码
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e5 + 10;
int n , m , a[MAXN] , temp;
int main(){
cin >> n >> m;
for(int i = 1; i <= n; ++i){
cin >> a[i];
cout << temp / m << " ";
temp += a[i];
}
return 0;
}
T2 凯撒加密
题目描述
恺撒密码是一种广为人知的加密技术。恺撒把需要加密的字母按字母表向后移动 33 位,替换成密文字母。例如,所有的 A 将被变成 D,B 变成 E 等等。若要加密最后三个字母,则需要折回到前三个字母,比如 x 变 a,y 变 b,z 变 c。
例如以下明文
T
h
e
Q
u
i
c
k
B
r
o
w
n
F
o
x
J
u
m
p
s
O
v
e
r
T
h
e
L
a
z
y
D
o
g
TheQuickBrownFoxJumpsOverTheLazyDog
TheQuickBrownFoxJumpsOverTheLazyDog
将被加密成
W
k
h
T
x
l
f
n
E
u
r
z
q
I
r
a
M
x
p
s
v
R
y
h
u
W
k
h
O
d
c
b
G
r
j
WkhTxlfnEurzqIraMxpsvRyhuWkhOdcbGrj
WkhTxlfnEurzqIraMxpsvRyhuWkhOdcbGrj
给定一段只由拉丁字母组成的字符序列,请将它用凯撒加密成密文。
输入格式
一个字符序列:表示需要加密的明文
输出格式
一个字符序列:表示加密后的密文
数据范围
设输入的字符数量为 n n n,则保证 1 ≤ n ≤ 100 , 000 1leq nleq 100,000 1≤n≤100,000
样例数据
输入:
T h e Q u i c k B r o w n F o x J u m p s O v e r T h e L a z y D o g TheQuickBrownFoxJumpsOverTheLazyDog TheQuickBrownFoxJumpsOverTheLazyDog
输出:
W k h T x l f n E u r z q I r a M x p s v R y h u W k h O d c b G r j WkhTxlfnEurzqIraMxpsvRyhuWkhOdcbGrj WkhTxlfnEurzqIraMxpsvRyhuWkhOdcbGrj
思路
xyz特判一下,其他直接加上输出
代码
#include <bits/stdc++.h>
using namespace std;
char ch;
int main(){
while(cin >> ch){
if(ch == 'x') cout << 'a';
else if(ch == 'y') cout << 'b';
else if(ch == 'z') cout << 'c';
else if(ch == 'X') cout << 'A';
else if(ch == 'Y') cout << 'B';
else if(ch == 'Z') cout << 'C';
else cout << char(ch + 3);
}
return 0;
}
T3 找零
题目描述
有一台自动售票机,每张票卖 5 元。售票机可以接受 5 元、10 元、20元的纸币。接受大面额纸币时,若没有足够的零钱,售票机将拒绝售票并将纸币退还给客户,若有零钱足够,售票机必须出票并且找零。
一开始,售票机里没有任何零钱。
每位客户只买一张票也只会塞一张纸币。按照购票顺序,给定售票机收到的 n 张纸币的面额。请统计售货机最多能够卖出多少张票。
输入格式
第一行:单个整数 n
第二行:n 个整数表示 n 名客户分别塞入的纸币面额,保证只能是 5、10、20 中的一个。
输出格式
单个整数:表示售票机卖出的最多票数。
数据范围
1 ≤ n ≤ 50 , 000 1leq nleq 50,000 1≤n≤50,000
样例数据
输入:
8
10 5 5 5 10 10 20 20
输出:
6
说明:
由于没有零钱,无法把票卖给第一个人和最后一个人
思路
简单贪心,优先找出10元纸票,5元可以找10元和20元,10元只可以找20元,优先保留5元
代码
#include <bits/stdc++.h>
using namespace std;
int n , temp , s1 , s2 , ans;
int main(){
cin >> n;
for(int i = 1; i <= n; ++i){
cin >> temp;
if(temp == 5){
s1++;
ans++;
}
if(temp == 10){
if(s1){
s1--;
s2++;
ans++;
}
}
if(temp == 20){
if(s1 && s2){
s1--;
s2--;
ans++;
}
else if(s1 >= 3){
s1 -= 3;
ans++;
}
}
}
cout << ans << endl;
return 0;
}
T4 新年灯会
题目描述
新春佳节之际,路上挂起了一排喜气洋洋的大红灯笼,从左至右编号分别为 1 , 2 , . . . , n . 1,2,...,n. 1,2,...,n.但小爱发现,目前有 p p p个灯笼不亮了,很是影响美观。
请你帮助小爱计算,最少修复多少个灯笼,便可使道路上有连续 m m m个亮着的大红灯笼?
输入格式
输入共两行:
第一行,三个正整数分别表示
n
,
m
,
p
n,m,p
n,m,p
第二行,
p
p
p个正整数,表示已经不亮的灯笼编号
输出格式
输出共一行,一个正整数表示答案
数据范围
对于
30
%
30%
30% 的数据,
1
≤
m
,
p
≤
n
≤
100
1 leq m,p leq n leq 100
1≤m,p≤n≤100
对于
60
%
60%
60% 的数据,
1
≤
m
,
p
≤
n
≤
1
0
4
1leq m,p leq n leq 10^4
1≤m,p≤n≤104
对于
100
%
100%
100% 的数据,
1
≤
m
,
p
≤
n
≤
1
0
5
1 leq m,p leq n leq 10^5
1≤m,p≤n≤105
样例数据
输入:
8 5 3
5 1 8
输出:
1
说明:
只需把5号灯笼修好即可
思路
处理出每两个坏掉灯笼之间的好的灯笼数量,双指针指向每个坏掉的灯笼,计算出修好最少灯笼以达到 m 个,计算出每次打擂台输出最小值
代码
#include <bits/stdc++.h>
using namespace std;
const int MAXP = 1e5 + 10;
int n , m , p , a[MAXP] , s[MAXP];
int main(){
cin >> n >> m >> p;
for(int i = 1; i <= p; ++i)
cin >> a[i];
sort(a + 1 , a + 1 + p);
for(int i = 1; i < p; ++i)
s[i] = a[i + 1] - a[i] - 1;
s[0] = 0 , s[p] = n - a[p];
int l = 1 , r = 1 , temp = 0 , ans = 1e6;
while(l <= p){
if(temp >= m){
ans = min(ans , r - l);
temp = temp - s[l - 1] - 1;
l++;
}
else{
temp += s[r] + 1;
r++;
}
}
cout << ans << endl;
return 0;
}
T5 积木染色(二)
题目描述
n n n 块积木排成一排,需要给每块积木染色,颜色有 m m m 种。请问有多少种方法,从第二块积木开始统计,恰有 p p p 块积木与前一块积木颜色不同?
输入格式
三个整数分别表示 n , m , p n,m,p n,m,p
输出格式
输出满足条件的方案数模10^9+7的结果
数据范围
对于$30% $的数据,
1
≤
n
,
m
≤
10
1 leq n,m leq 10
1≤n,m≤10
对于$60% $的数据,
1
≤
n
,
m
≤
500
1 leq n,m leq 500
1≤n,m≤500
对于
100
%
100%
100% 的数据,
1
≤
n
,
m
≤
5000
1 leq n,mleq 5000
1≤n,m≤5000
1
≤
p
<
n
1 leq p lt n
1≤p<n
样例数据
输入:
4 2 2
输出:
6
说明:
设两种颜色分别为1,2
则有:1121,1211,1221,2122,2112,2212共计6种
思路
考虑递推
直接定义状态
1.n > 1 并且p > 0的情况 如果颜色与前一个相同,则是 f ( n , p ) = f ( n − 1 , p ) f(n , p) = f (n - 1 , p) f(n,p)=f(n−1,p)
如果颜色与前一个不同 , 则考虑乘法原理 ,颜色要减一
f ( n , p ) = ( m − 1 ) ∗ f ( n − 1 , p − 1 ) f(n , p) = (m - 1) * f(n - 1 , p - 1) f(n,p)=(m−1)∗f(n−1,p−1) 两者相加
p = 0 p = 0 p=0 则 f ( n , p ) = f ( n − 1 , p ) f(n , p) = f (n - 1 , p) f(n,p)=f(n−1,p)
2 n = 1为界限如果p = 0则有m种情况 , p > 0 无解
代码
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 5010;
const int mod = 1e9 + 7;
#define int long long
int m , dp[MAXN][MAXN];
int f(int n , int p){
if(dp[n][p] != -1)
return dp[n][p];
else if(n == 1){
if(p == 0) return dp[n][p] = m;
else return dp[n][p] = 0;
}
if(p > 0)
return dp[n][p] = f(n - 1 , p) % mod + (m - 1) * f(n - 1 , p - 1) % mod;
if(p == 0)
return dp[n][p] = f(n - 1 , p) % mod;
}
signed main(){
int n , p;
cin >> n >> m >> p;
memset(dp , -1 , sizeof(dp));
cout << f(n , p) % mod << endl;
return 0;
}
最后
以上就是知性店员为你收集整理的上海市计算机学会竞赛 2023.1 丙组月赛上海市计算机学会竞赛 2023.1 丙组月赛的全部内容,希望文章能够帮你解决上海市计算机学会竞赛 2023.1 丙组月赛上海市计算机学会竞赛 2023.1 丙组月赛所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复