上海市计算机学会竞赛 2023.1 丙组月赛

上海市计算机学会竞赛 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 1\leq n\leq 10 1n10
对于 60 % 60\% 60% 的数据, 1 ≤ n ≤ 1 0 4 1 \leq n\leq 10^4 1n104
对于 100 % 100\% 100% 的数据, 1 ≤ n ≤ 1 0 5 1\leq n\leq 10^5 1n105

1 ≤ m , a i ≤ n 1\leq m,a_i\leq n 1m,ain
样例数据

输入:

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 1\leq n\leq 100,000 1n100,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 1\leq n\leq 50,000 1n50,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 1m,pn100
对于 60 % 60\% 60% 的数据, 1 ≤ m , p ≤ n ≤ 1 0 4 1\leq m,p \leq n \leq 10^4 1m,pn104
对于 100 % 100\% 100% 的数据, 1 ≤ m , p ≤ n ≤ 1 0 5 1 \leq m,p \leq n \leq 10^5 1m,pn105

样例数据

输入:
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 1n,m10
对于$60% $的数据, 1 ≤ n , m ≤ 500 1 \leq n,m \leq 500 1n,m500
对于 100 % 100\% 100% 的数据, 1 ≤ n , m ≤ 5000 1 \leq n,m\leq 5000 1n,m5000
1 ≤ p < n 1 \leq p \lt n 1p<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(n1,p)
如果颜色与前一个不同 , 则考虑乘法原理 ,颜色要减一
f ( n , p ) = ( m − 1 ) ∗ f ( n − 1 , p − 1 ) f(n , p) = (m - 1) * f(n - 1 , p - 1) f(n,p)=(m1)f(n1,p1) 两者相加
p = 0 p = 0 p=0 f ( n , p ) = f ( n − 1 , p ) f(n , p) = f (n - 1 , p) f(n,p)=f(n1,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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值