算法竞赛入门【码蹄集进阶塔335题】(MT2001-2025)
文章目录
- 算法竞赛入门【码蹄集进阶塔335题】(MT2001-2025)
- 前言
- 为什么突然想学算法了?
- 为什么选择码蹄集作为刷题软件?
- 目录
- 1. MT2001 幸运的3
- 2. MT2002 买马
- 3. MT2003 三角数
- 4. MT2004 购买数字
- 5. MT2005 高次方程
- 6. MT2006 可怜的小码哥
- 7. MT2007 九次九日九重色
- 8. MT2008 寻找串
- 9. MT2009 好的三连
- 10. MT2010 捉迷藏
- 11. MT2011 花园浇水
- 12. MT2012 竹鼠的白色季节
- 13. MT2013 照亮街道
- 14. MT2014 打靶
- 15. MT2015 线段覆盖
- 16. MT2016 数据流中的中位数
- 17. MT2017 连续的串
- 18. MT2018 找1
- 19. MT2019 挑兵挑将
- 20. MT2020 三合一
- 21. MT2021 跳蚤
- 22. MT2022 疯狂算钱
- 23. MT2023 序列操作
- 24. MT2024 水位线
- 25. MT2025 工厂
- 结语
前言
为什么突然想学算法了?
> 用较为“官方”的语言讲,是因为算法对计算机科学的所有分支都非常重要。 在绝大多数的计算机科学分支领域中,要想完成任何实质性的工作,理解算法的基础知识并掌握与算法密切相关的数据结构知识是必不可少的。
> 但从实际而言,是因为当下快到了考研和找工作的年纪(ಥ_ಥ),无论走哪一条路,都不免需要一些相对丰富的算法知识,是故,便产生了一个暑假速成算法的计划,可能对于像我这种算法竞赛小白而言,几乎很难,但我仍然还是想尝试一下,毕竟,梦想还是要有的,万一实现了呢?~( ̄▽ ̄~)~
为什么选择码蹄集作为刷题软件?
码蹄集,是在全国高等学校计算机教学与产业实践资源建设专家委员会(TIPCC) 指导下建设的,其依托全国各大名校计算机系和清华大学出版社等单位的强大资源,旨在为计算机学习爱好者提供全面和权威的计算机习题。
目录
1. MT2001 幸运的3
(1)题目描述
你有n个数,可以将它们两两匹配(即将两数首尾相连),每个数只能使用一次,问匹配后最多有多少个3的倍数(没有进行匹配的数不算)?
格式
输入格式: 第一行一个n,接下来n个正整数。
.
输出格式: 输出最多有多少个3的倍数.
样例1
输入:
3
123 123 99
.
输出: 1
备注:
其中:1≤n ≤10000,1 ≤ a ≤100000000
(2)参考代码
import time
from typing import List, Tuple
from collections import deque, Counter
from queue import PriorityQueue
import math
from functools import lru_cache
import random
import copy
import sys
sys.setrecursionlimit(99999999)
MOD = 10**9+7
def bit_sum(x):
tot=0
while x:
tot+=x%10
x //= 10
return tot%3
def main():
n = int(input())
arr = map(int,input().split())
c = [0]*3
for v in arr:
c[bit_sum(v)] +=1
print(c[0]//2+min(c[1],c[2]))
if __name__ == '__main__':
main();
2. MT2002 买马
(1)题目描述
在市场当中,每一个编号为i的马都住在相应编号为i的马厩中,现在小码哥想要在市场里购买一定数量的马匹,由于市场很大,小码哥可以买回编号非常大的马匹回来,但是小码哥的牧场并没有这么大,使得马匹住在相应编号的马厩中。但聪明的小码哥想到可以使用某种哈希映射来解决该问题。他想出的方法是对它们进行取模操作(即编号为s的马住在小码哥家编号为s ;modk 的马厩里)。现在已经知道了买回来马匹的编号,你是否可以找到一个最小的k来完成此映射,使得每一匹马单独住在一个马厩中。(注意小码哥家有编号为0的马厩)
格式
输入格式:
第一行一个整数n表示小码哥买回来马匹的总数(马的数量不超过100 )。
接下来n行,每一行一个数字s,表示第i匹马的编号(马的编号为不超过1000的正整数)。
.
输出格式: 一个整数,表示要求的最小的K。
样例1
输入:
3
1
2
6
.
输出: 3
(2)参考代码
#include <bits/stdc++.h>
using namespace std;
const int N = 101, K = 1000;
int main() {
int n, aa[N]={0};
cin >> n;
for (int i = 0; i < n; i++)
cin >> aa[i];
for (int i = n; i <= K; i++) {
bool f[K] = {0};
bool flag = true;
for (int j = 0; j < n; j++) {
int remain = aa[j] % i;
if (!f[remain])
f[remain] = true;
else {
flag = false;
break;
}
}
if (flag) {
cout << i;
return 0;
}
}
return 0;
}
3. MT2003 三角数
(1)题目描述
格式
输入格式: 第一行: n (1≤n ≤1e9)
.
输出格式: 如果是,输出YES,否则输出NO。
样例1
输入: 256
.
输出: YES
(2)参考代码
#include<bits/stdc++.h>
//先用哈希表把mxr数存下来,然后查表
using namespace std;
typedef long long ll;
unordered_map<int, bool> mp;
int main( )
{
//哈希表把mxr数 存下来
for(int i=0;(ll)i *(i+1)<=1e9;++i) mp[i*(i+1)]=true;
int n;
cin>>n;
n = 2*n;
for(auto it:mp){
//a是mxr,n-a也得是mxr
if(2*it.first <n&&mp[n-it.first]==true){
cout<<"YES"<<endl;
return 0;
}
}
cout<<"NO";
return 0;
}
4. MT2004 购买数字
(1)题目描述
小码哥是数学王国的一位居民,最近他迷上了回文数,决定去数字商店购买一个回文数。小码哥是个比较贪心的孩子,他想要购买自己能买到的最大的回文数,已知每个数的价格是这个数本身(即1是1块钱,2是2块钱…)。
小码哥家由于是个数学世家,小码哥的零花钱也比别人多一点点,目前小码哥手上有n块钱,小码哥想问你他能买到的最大的回文数是多少?
格式
输入格式: 一个正整数n,表示小码哥的零花钱,其中可能有前导零。
.
输出格式: 输出一个正整数,表示小码哥能买到的最大的回文数。
样例1:
输入: 648
.
输出:646
(2)参考代码
def main():
num_str = input()
for i in range(len(num_str)):
if num_str[i]!='0':
break
num_str = num_str[i:]
num = int(num_str)
num_reverse = num_str[::-1]
if num_reverse[len(num_str)//2:] > num_str[len(num_str)//2:]:
if num == 10**(len(num_str)-1):
print(num-1)
elif len(num_str)%2 ==0:
prefix = str(int(num_str[:len(num_str)//2])-1)
postfix = prefix[::-1]
print(prefix+postfix)
else:
prefix = str(int(num_str[:len(num_str)//2+1])-1)
postfix = prefix[:-1][::-1]
print(prefix+postfix)
elif num_reverse[len(num_str)//2:] < num_str[len(num_str)//2:]:
num_list = list(num_str)
num_list[len(num_str)//2:] = list(num_reverse[len(num_str)//2:])
print("".join(num_list))
else:
print(num)
if __name__ == '__main__':
main();
5. MT2005 高次方程
(1)题目描述
格式
输入格式: 三个数:A,B,n (1≤n ≤10)。
.
输出格式: 按题目要求输出一行一个整数X或者No solution。
样例1
输入: 2 11 2
.
输出: -3
(2)参考代码
#include<bits/stdc++.h>
using namespace std;
int main()
{
int A,B,n,x;
cin>>A>>B>>n;
x=B-A;
for(int i=-2000;i<=2000;i++){
int mul=1;
for(int j=0;j<n;j++) mul*=i;
if(mul==B-A){
cout<<i;
return 0;
}
}
cout<<"No solution";
}
6. MT2006 可怜的小码哥
(1)题目描述
提瓦特大陆上有一个贫穷的占星术士小码哥,出于占星术的要求,他时常要解决一些困难的数学问题。这天,他有遇到一个难题:对于一给定的素数集合S=P1, P2,. . . , p% ,考虑一个正整数集合,该集合中任一元素的质因数全部属于S。这个正整数集合包括,pi、p1× p2、p1× p1、P1×P2× p3…(还有其它)。该集合被称为S集合的“丑数集合”。小码哥现在的工作是对于给定的集合S,去寻找“丑数集合”中的第 n个“丑数”。
说明:丑数集合中每个数从小到大排列,每个丑数都是素数集合中的数的乘积,第n个丑数”就是在能由素数集合中的数相乘得来的(包括它本身)第n小的数。
格式
输入格式:
输入的第一行是两个的整数|S| ,n,分别代表集合S的大小|S和给定的参数n。
输入的第二行有|S|个互不相同的整数,第i个整数代表pi
.
输出格式: 输出一行一个整数,代表答案。
样例1
输入:
4 19
2 3 5 7
.
输出: 27
(2)参考代码
/*
整体思路:
1. 定义了一个集合t,减少了后续的排序,删除重复元素等麻烦
2. 对输入的数据进行遍历,求出符合条件的pi,放入集合t中
3. 由于set容器的自动排序,且默认为从小到大排序的特点,所以只需要获取set容器中第n个元素,输出即可
*/
#include<bits/stdc++.h>
using namespace std;
//定义pi值的最大值,2的31次-1(虽然pi最大可取2的31次,但由于pi为质数,所以最大应为2的31次-1)
int ma=pow(2,31)-1;
set<long long>t; //定义集合t
/*
set容器的一些性质:
1. 所有元素都会在插入时自动被排序,默认排序为升序,即从小到大
(该性质可以使得我们在后面的操作中不需要再进行排序代码的编写)
2. set不允许容器中有重复的元素
3. set属于关联式容器,底层结构是用二叉树实现的
*/
int a[10005]; //设置数组a,用来存放输入的pi
int main( )
{
int m,n; //定义整数S和n
cin>>m>>n; //输入S和n
for(int i=1;i<=m;i++){ //第二行的输入,将题中的元素放到集合t中
cin>>a[i];
t.insert(a[i]);
}
//由于丑数集合是从小到大排列的,所以只需要遍历n次即可
while(t.size()<=n){
for(auto i=t.begin();i != t.end();i++){ //对集合t进行遍历,进行条件筛选
for(int j=1;j<=m;j++){ //对S中的元素进行遍历
//筛选pi值不符合要求的元素,如果小于ma,则放入集合t中,否则就不放,进行下一次遍历
if(a[j]*(*i)>ma) break;
t.insert(a[j]*(*i)); //将符合条件的元素放入集合t中
}
}
}
auto ans=t.begin(); //定义ans为集合中的第1个数
for(int i=1;i<n;i++){ //对ans进行加法运算,求得其集合t中的第n个数,也就是我们要输出的结果
ans++;
}
printf("%lld\n",*ans);
return 0;
}
7. MT2007 九次九日九重色
(1)题目描述
小码哥是一个喜欢字符串的男孩子。
如果一个字符串 s可以由一个字符串集合P中的元素拼接得到,我们就称s可以分解为P。
现在有一个字符串集合P和一个字符串 s ,他想知道s最长的可以分解为P的前缀有多长。请你帮帮他!
格式
输入格式:
输入的开头有若干个字符串,以空格或换行隔开,它们是集合P中的元素。
集合的结束标志是.,之后若干行,每行有一个字符串,s为将这些字符串拼接得到的串。
.
输出格式: 输出一个整数,表示s 最长的可以分解为P的前缀的长度。如果s 的所有前缀都无法分解为P,请输出一个0。
样例1
输入:
A AB BA CA BBC
.
ABABACABAABC
.
输出: 11
(2)参考代码
import java.util.Scanner;
import java.util.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner input=new Scanner(System.in);
int n=input.nextInt();
input.nextLine();
Map<String,Integer> map=new HashMap<String,Integer>();
for(int i=0;i<n;i++){
String s=input.nextLine();
if(map.containsKey(s)){
map.put(s,map.get(s)+1);
}else{
map.put(s,map.getOrDefault(s,0));
}
if(map.get(s)==0){
System.out.println("OK");
}else{
System.out.println(s+map.get(s).toString());
}
}
}
}
8. MT2008 寻找串
(1)题目描述
在所给字符串中找出最少出现两次的最长子串的长度,没有则输出0。
格式
输入格式: 这一定是非空的字符串S,并由小写字母组成。
.
输出格式: 输出一个数。这个数是子串中最少出现两次的最长子串的长度。
样例1
输入: ababa
.
输出: 3
备注:
其中:|S|≤100
(2)参考代码
def main():
s = input()
substring = ""
for i in range(len(s)):
while s[i:i+len(substring)+1] in s[i+1:]:
substring = s[i:i+len(substring)+1]
print(len(substring))
if __name__ == '__main__':
main();
9. MT2009 好的三连
(1)题目描述
给出e1串S,求[1,r]区间个数,使得至少能找到一对[a,k],满足1≤a, k ≤|S|且 l≤a <优 +k<t +2k≤r 且 S[a]= S[a +k]=S[a + 2k]。
格式
输入格式: 输入一个01字符串
.
输出格式: 输出一个数,即答案
样例1
输入: 010101
.
输出: 3
备注:
其中: 3≤|S≤3e5, 1≤l<r≤|S,字符串下标从1开始。
(2)参考代码
#include <bits/stdc++.h>
#define int LL
#define LL long long
#define ULL unsigned long long
#define CF int tt;std::cin >> tt;while(tt--){solve();}
using namespace std;
inline int read(){
int a=0,po=1;char ch=getchar();
while (!isdigit(ch)&&ch!='-') ch=getchar();
if (ch=='-') po=-1,ch=getchar();
while (isdigit(ch)) a=a*10+ch-'0',ch=getchar();
return a*po;
}
string x;
int a[1000010];
int c[1000010];
signed main(){
cin>>x;
int len=x.length();
int ans=0;
for (int i=0;i<len;i++){
c[i]=len+1;
}
for (int i=0;i<len-2;i++){
int r=-1;
for (int j=1;j<=len;j++){
if (i+2*j<len&&x[i]==x[i+j]&&x[i]==x[i+2*j]){
r=i+2*j;
break;
}
if (i+2*j>=len){
break;
}
}
if (r!=-1){
c[i]=r;
}
}
int tmp=c[len-1];
if (tmp!=len+1) ans+=tmp;
for (int i=len-1;i>=0;i--){
// cout<<c[i]<<endl;
tmp=min(tmp,c[i]);
if (tmp!=len+1) ans+=(len-tmp);
}
cout<<ans;
}
10. MT2010 捉迷藏
(1)题目描述
给n 个单元格,这n个单元格在同一行,将一个代币放在单元格内,让另一个人猜代币放在哪了(视为一次询问)。可以选择在某一次询问之前或之后,将代币移动到所在单元格旁边两个单元格之一(移动操作在全部询问过程中至多进行一次,至少零次)。问在依次进行m次询问后依旧找不到代币的情况(代币位置的改变)有几种?
格式
输入格式:
第一行n,m
第二行m个数a[i],表示询问
.
输出格式: 输出仅一行,为所求答案
样例1
输入:
5 3
5 1 4
.
输出: 9
(2)参考代码
#include <bits/stdc++.h>
#define endl "\n"
#define debug(x) cout << "*----" << x << "----*" << endl
#define show(x) cout << #x "=" << x << endl
using namespace std;
typedef long long ll;
const int N = 1e6 + 7;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
int l[N], r[N];//l表示一个询问a出现最早的位置,r表示最晚的位置
int main()
{
int n, m;
cin >> n >> m;
memset(l, 0x3f, sizeof l);
for (int i = 1; i <= m; i++) {
int x;
cin >> x;
l[x] = min(l[x], i);
r[x] = max(r[x], i);
}
int ans = 0;
//位置1和位置n单独考虑
if (r[1] == 0)
ans += 2;
else if (r[2] < l[1])
ans++;
if (r[n] == 0)
ans += 2;
else if (r[n - 1] < l[n])
ans++;
for (int i = 2; i < n; i++) {
//如果询问i没有出现过,那么(i->i),(i->i+1),(i->i-1)三种情况总是合法的,对于(i->i+1)和(i->i-1),可以在最后一个询问之后将代币移动到另一个位置
if (r[i] == 0) ans += 3;
else {
if (r[i - 1] < l[i])
ans++;
if (r[i + 1] < l[i])
ans++;
}
}
if (n == 1)
ans = 0;
cout << ans << endl;
return 0;
}
11. MT2011 花园浇水
(1)题目描述
小码哥需要给花园浇水。花园是1×n的长方形。每块地有一个高度。他会选择一块地方浇水,如果与这块地相邻的区域的高度小于等于这块地的高度,水就可以流过去,直到不能流为止。求他一次最多可以浇灌多少块地。
格式
输入格式:
第一行为一个正整数n,
第二行为初始高度。
.
输出格式: 输出一行一个整数表示答案。
样例1
输入:
8
1 2 1 1 1 3 3 4
.
输出: 6
备注:
所有数据均不大于1000,并且均非负。
(2)参考代码
#include <cstdio>
#include <algorithm>
using namespace std;
int n,a[1005],ans;
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=1;i<=n;i++)
{
int l=i,r=i,ln=a[i],rn=a[i];
while(l>1&&a[l-1]<=ln)
ln=a[--l];
while(r<n&&a[r+1]<=rn)
rn=a[++r];
ans=max(ans,r-l+1);
}
printf("%d\n",ans);
return 0;
}
12. MT2012 竹鼠的白色季节
(1)题目描述
格式
输入格式:
第一行,两个用空格隔开的数字n和d。
第二行,n个整数,分别表示n只竹鼠在直线上的坐标。
.
输出格式: 输出一个整数,则有缘竹鼠对。
样例1
输入:
5 3
1 2 4 8 9
.
输出: 4
(2)参考代码
#include<bits/stdc++.h>
using namespace std;
int a[1000001],n,d,i,j,k;
int main( )
{
cin>>n>>d;
for(i=1;i<=n;i++) cin>>a[i];
k=0;
sort(a+1,a+(n+1));
for(i=1;i<n;i++)
for(j=i+1;j<=n;++j){
if(a[j]-a[i]>d) break;
++k;
}
cout<<k;
return 0;
}
13. MT2013 照亮街道
(1)题目描述
有一条可以视为线段的街道,长度为L,其中有n个路灯,每个路灯能照亮的半径都是相同的,求最小的照亮半径r使得整条街道上的每一个点都能被照亮。
格式
输入格式:
两个正整数n,L
第二行为初始n个实数,表示n个路灯的坐标数据保证在0到L之间
.
输出格式: 输出一行一个整数表示答案,答案保留两位小数。
样例1
输入:
7 15
15 5 3 7 9 14 0
.
输出: 2.50
备注:
其中: n≤1000,L≤ 1e9
(2)参考代码
#include<iostream>
#include<vector>
#include<iomanip>
using namespace std;
int main()
{
int n;
double L;//改变了类型
cin >> n >> L;
vector<double>a;
//用容器输入基本的信息
for (int i = 0; i < n; i++)
{
double b;
cin >> b;
a.push_back(b);
}
//下面使用冒泡排序
for (int i = 0; i < n; i++)
{
for (int j = i + 1; j < n; j++)
{
if (a[i] > a[j])
{
double temp = a[j];
a[j] = a[i];
a[i] = temp;
}
}
}
double max = a[1] - a[0];
for (int i = 1; i < n - 1; i++)
{
if (a[i + 1] - a[i] > max)
{
max = a[i + 1] - a[i];
}
}
max = max / 2;
if (L - a[n - 1] > max)
{
max = L - a[n - 1];
}
if (a[0] > max)
{
max = a[0];
}
cout << setiosflags(ios::fixed) << setprecision(2) << max<< endl;
}
14. MT2014 打靶
(1)题目描述
格式
输入格式:
第一行一个整数n。
第二行n个整数hi。
.
输出格式: 输出一个整数,表示小码哥最少需要射几箭。
样例1
输入:
5
2 1 5 4 3
.
输出: 2
备注:
小码哥站位和靶子放置位置:
小码哥—>靶子1,靶子2,靶子3,…,靶子n
不会有两个相邻的靶子紧紧贴在一起
(2)参考代码
#include<bits/stdc++.h>
using namespace std;
int h,n,ans,a[1000001];
int main()
{
scanf("%d",&n);
while(n--)
scanf("%d",&h),a[h]?a[h]--:ans++,a[h-1]++;
printf("%d",ans);
return 0;
}
15. MT2015 线段覆盖
(1)题目描述
现给定一根坐标轴,坐标轴上有n条线段,每条线段从1开始编号,若线段编号为k,则该线段覆盖的区间是:[(k 一1) x m,(k 一 1)x m+l]。
有一个质点从原点开始向x轴正半轴移动,每次移动d距离。问第一个不被线段覆盖的点的位置在哪里?
格式
输入格式:
一行四个正整数n,d,m,l,意义见题面。保证1≤n, d, m,l ≤le6,并且l<m 。
.
输出格式: 一行一个数表示答案
样例1
输入: 5 4 11 8
.
输出: 20
(2)参考代码
#include <iostream>
using namespace std;
long long n, m, d, l;
int main() {
cin >> n >> d >> m >> l;
long long a = 0, b = 0;
for (long long i = 1; i <= n; i++) {
a = (i - 1) * m + l, b = i * m - 1;
if (a / d != b / d) break;
}
cout << (a / d + 1) * d << endl;
return 0;
}
16. MT2016 数据流中的中位数
(1)题目描述
格式
输入格式:
第一行输入一个整型n(n ≤100000)
第二行输入n个操作
.
输出格式: ?询问时输出中位数,每个操作一行,保证每次查询都合法
样例1
(2)参考代码
#include <stdio.h>
#include <string>
#include <string.h>
#include <algorithm>
#include <map>
#include <vector>
#include <algorithm>
#include <vector>
#include <set>
#include <queue>
#include <string>
#include <unordered_map>
using namespace std;
const int N = 6000005;
char buf[6000005];
char val[6000005];
int main()
{
int n, m;
scanf("%d %d", &n, &m);
scanf("%s", val);
int jj = n-1;
scanf("%s", buf);
for (int i = 0; i < m; i++) {
char op = buf[i];
if (op == '*') {
jj++; val[jj] = '0';
} else if (op == '/') {
if (jj >= 1) {
jj --;
} else {
val[jj] = '0';
}
} else if (op == '+') {
for (int k = jj; k >= 1; k--) {
if (val[k] == '0') {
val[k] = '1'; break;
} else {
val[k] = '0';
}
}
} else {
for (int k = jj; k >= 1; k--) {
if (val[k] == '1') {
val[k] = '0'; break;
} else {
val[k] = '1';
}
}
}
}
val[jj+1] = '\0';
printf("%s\n", val);
return 0;
}
17. MT2017 连续的串
(1)题目描述
给你一个字符串,找出现次数最多的长度为2的子串。
格式
输入格式: 第一行为一个正整数n,表示给出字符串的长度,第二行为字符串
.
输出格式: 输出所求的串,若有多个结果,输出字典序最小的
样例1
输入: 7
ABACABA
.
输出: AB
备注:
其中:2≤n ≤100;字符串中只包含大写字母。
(2)参考代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
string s[5005];
map<string,ll>cccc;
int main(){
ll n,i,j,k,slsl=0,zd=0;
string sr,dq;
cin>>n>>sr;
for(i=0;i<=n-2;i++){
dq="AA";
dq[0]=sr[i],dq[1]=sr[i+1];
if(cccc[dq]==0) s[++slsl]=dq;
cccc[dq]++;
zd=max(zd,cccc[dq]);
}
sort(s+1,s+1+slsl);
for(i=1;i<=slsl;i++){
if(cccc[s[i]]==zd){
cout<<s[i]<<endl;
break;
}
}
return 0;
}
18. MT2018 找1
(1)题目描述
格式
输入格式: 一个二进制字符串
.
输出格式: 所有字符都为1的子串个数
样例1
输入: 0110111
.
输出: 9
(2)参考代码
#include<bits/stdc++.h>
using namespace std;
int numSub(string s){
vector<long int> tem;//用来储存连续出现1的个数
int modd = pow(10, 9) + 7;
for (int i = 0; i < s.length(); )
{
if (s[i] == '1')//当前字符为1,判断后面是否是连续的1
{
int c = 1;
while (i + 1 < s.length() && s[i + 1] == '1')
{
c++;
i++;
}
tem.push_back(c);//将连续1的个数存入tem
i++;
}
else
i++;
}
int sum =0;
for(int i=0;i<tem.size();i++)
{
tem[i]=(1+tem[i])*tem[i]/2%modd;//计算长度为n的连续1字符串有(1+n)*n/2种组合,计算完毕后求模,不然就超时或者溢出了
sum+=tem[i];
}
return sum;
}
int main( )
{
string s;
cin>>s;
int res = numSub(s);
cout<<res;
return 0;
}
19. MT2019 挑兵挑将
(1)题目描述
格式
输入格式: 可能有多组数据,每组一行输入三个整数n、k、m,输入0 0 0 停止。
.
输出格式: 输出每轮选出的人,用,隔开,每个编号占3个格子(右对齐)。
样例1
输入:
10 4 3
0 0 0
.
输出: 4 8, 9 5, 3 1, 2 6, 10, 7
备注:
0 <n ≤20 ; k、m 在int范围内,且为正数;组数少于20。
(2)参考代码
#include<bits/stdc++.h>
using namespace std;
char d[] = "0123456789ABCDEF";
struct node{
string s;
bool operator<(const node b) const{
if(s.size()!=b.s.size()) return s.size()<b.s.size();
return s<b.s;
}
};
set<node> st;
string a;
void dfs(int last){
if(a.size()>=1) st.insert({a});
for(int i=last+1;i<=15;i++){
a.push_back(d[i]);
dfs(i);
a.pop_back();
}
}
int main(){
string s;
cin>>s;
int f=1;
if(s[0]=='-') f=-1,s.erase(s.begin());
while(*s.begin()=='0'&&s.size()>1) s.erase(s.begin());
dfs(0);
map<string,int>mp;
int p=1;
mp["0"]=0;
for(auto u:st){
mp[u.s]=p++;
}
if(mp.find(s)==mp.end()) cout<<"error"<<endl;
else cout<<mp[s]*f<<endl;
return 0;
}
20. MT2020 三合一
(1)题目描述
有一个数组,每一个位置有一个1-9的数,现对其进行三合一操作
三合一操作有若干轮:每一轮,从前往后扫,如果三个相邻的数的和小于等于“轮次*3”,则这三个数合并为一个数。如果能合,本轮的下一次扫描就从三个数后面的第一个数开始扫;如果不能合,就从这三个数的第二个数开始扫。他们相加的和经过有限轮后,该数组肯定会变为一个数或两个数。
现在需要你求出一共进行了多少轮(没有进行任何操作的轮次也算)。
格式
输入格式:
第一行一个整数n
第二行n个整数
.
输出格式: 一行一个整数,表示进行了多少轮
样例1
输入:
3
1 2 3
.
输出: 2
备注:
其中:3≤n ≤10000
(2)参考代码
def main():
#code here
n = int(input())
arr = [int(x) for x in input().split()]
i = 1
while True:
flag = False
j = 0
while j<len(arr)-2:
s = sum(arr[j:j+3])
if s<= i*3:
del arr[j:j+3]
arr = arr[:j]+[s]+arr[j:]
j+=1
else:
j+=1
if len(arr) <=2:
print(i)
flag = True
break
if flag: break
i += 1
if __name__ == '__main__':
main();
21. MT2021 跳蚤
(1)题目描述
菜地上挖了n行m列个坑,有一只跳蚤可以从任意一个坑作为起点无限次跳跃,同一个坑也可以重复跳到,但跳蚤只能垂直或者水平方向跳坑,而且不能跳到菜地外(这时候它会改变方向保证自己不掉出去或者停止)。每一跳距离固定为s个坑,当s为1表示跳到垂直或者水平方向紧相邻的隔壁坑里。求跳蚤可以从多少个不同的坑起跳,可以满足能在菜地里到达的坑数量为最大。
格式
输入格式: 三个整数n, m,s
.
输出格式: 一个整数,起点的数量
样例1
输入: 2 3 1
.
输出: 6
备注:
其中: 1≤n, m,s ≤ 1e6
(2)参考代码
#include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
ll n,m,s;
inline int read(){
int f=1,x=0; char ch=getchar();
while(ch<'0' || ch>'9'){if(ch=='-') ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return f*x;
}
ll f(ll x,ll s){
return x%s==0?x:(x%s)*(x/s+1);
}
int main( )
{
n=read();
m=read();
s=read();
printf("%lld\n",f(n,s)*f(m,s));
return 0;
}
22. MT2022 疯狂算钱
(1)题目描述
在瞄星人赢得一场编程现场赛之后,他乘坐公交车返回学校。公共汽车的车费是220元。他在车上遇到了专门给别人替考的郭枪手。唶星人决定教训一下郭枪手,所以决定玩下面这个游戏。
起初,有一堆钱,里面包含了x张100元和y张10元。他们轮流从中取钱。哺星人先手拿。在每个回合里,他们每次必须从堆中拿出刚好220元。在轮到瞄星人时,如果他有多种方式可以从中取出220元,他会选择包含最大数量的100元纸币的方式。轮到郭枪手时,如果有多种方式可以取出220元,他会选择包含最多10元纸币的方式。如果轮到了瞄星人或郭枪手不能从堆中拿出220元,那么他就会失败。
请你确定这场游戏的胜利者。
格式
输入格式: 第一行包括两个用空格分隔开的整数x,y。(意义详见题面,0≤c, g ≤10的6次 )
.
输出格式: 如果瞄星人能赢,那就输出xmg,否则输出gqs
样例1
输入: 3 22
.
输出: gqs
(2)参考代码
#include<bits/stdc++.h>
using namespace std;
int main() {
long long int x, y, flag = 1;
cin >> x >> y;
while ((100 * x + 10 * y >= 220)&&y>=2) {
//xmg回合
if (flag % 2 != 0) {
if (x >= 2 && y >= 2) {
x -= 2;
y -= 2;
}
else if (x >= 1 && y >= 12) {
x -= 1;
y -= 12;
}
else if (y >= 22) {
y -= 22;
}
}
//gqs回合
else {
if (y >= 22) {
y -= 22;
}
else if (x >= 1 && y >= 12) {
x -= 1;
y -= 12;
}
else if (x >= 2 && y >= 2) {
x -= 2;
y -= 2;
}
}
flag++;
}
if (flag % 2 != 0)
cout << "gqs" << endl;
else
cout << "xmg" << endl;
return 0;
}
23. MT2023 序列操作
(1)题目描述
格式
输入格式:
第一行2个正整数n, target ( n, tar get ≤ 100)
接下来一行n个正整数,表示这个数列。
.
输出格式: 按题目要求输出一行一个整数,表示最小操作次数。
样例1
输入:
4 3
1 1 1 1
.
输出: 5
(2)参考代码
def main():
#code here
n,t=map(int,input().split())
lis=list(map(int,input().split()))
res=0
while sum(lis)<t*n:
for i in range(n):
if i==n-1 and lis[n-1]<t:
lis[n-1]+=1
if i<n-1 and lis[i]!=lis[i+1] and lis[i]<t:
lis[i]+=1
res+=1
print(res)
if __name__ == '__main__':
main();
24. MT2024 水位线
(1)题目描述
饮水机中本来有k升水,小码希望在t天内饮水机的水量在[1,r]之间,小码知道每一天饮水机会被用掉正好a升水,而小码可以在一天的开始选择加正好y升水(一天只能加一次)或不加水。
给出 k,l, r , t, ac, g ,求能否在t天内把水量控制在[1,r],能输出Yes,否则输出No
格式
输入格式: 仅一行为k,l, r ,t, ,y
.
输出格式: 输出Yes或者No
样例1
输入: 8 1 10 2 6 4
.
输出: No
备注:
其中: 1<l≤k≤r ≤le9,1<t ≤ 1e9,1 ≤n ≤1e6,1≤y ≤1e9
(2)参考代码
#include<bits/stdc++.h>
using namespace std;
int main( )
{
long long k,l,r,t,x,y,i,j,w;
cin>>k>>l>>r>>t>>x>>y;
int flag=1;
w=k;
for(i=0;i<t;i++){
if(w+y <=r) w+=y;
if(w-x<1){
flag=0;
break;
}
w-=x;
}
if(flag) cout<<"Yes"<<endl;
else cout<<"No"<<endl;
return 0;
}
25. MT2025 工厂
(1)题目描述
有一个工厂,在一天的开始时,共有α个罐头,在这一天结束时,会生产a modm个罐头。
现在已知第一天所拥有的罐头数a ,以及m的值
请问,是否存在一个时刻,整个工厂会停止生产( amod m = 0 ) ?
格式
输入格式: 两个数a, m
.
输出格式: 当生产会停止时,输出ves,否则输出No
样例1
输入: 1 5
.
输出: No
备注:
其中:1≤a, m ≤ 1e5
(2)参考代码
#include<bits/stdc++.h>
using namespace std;
int a,m,cnt;
inline int read(){
int f=1,x=0;
char ch=getchar();
while(ch<'0' || ch >'9'){
if(ch=='-') f=-1;
ch = getchar();
}
while(ch>='0'&&ch<='9'){
x = x*10+ch-'0';
ch=getchar();
}
return f*x;
}
int main() {
a=read();
m=read();
while(a%m!=0){
a=a+a%m;
cnt++;
if(cnt>100000){
printf("No\n");
return 0;
}
}
printf("Yes\n");
return 0;
}
结语
感谢大家一直以来的不断支持与鼓励,码题集题库中的进阶塔350题正在逐步更新,之后会逐步跟进星耀,王者的题,尽请期待!!!
同时,也希望这些题能帮助到大家,一起进步,祝愿每一个算法道路上的“苦行僧”们,都能够历经磨难,终成正果,既然选择了这条路,走到了这里,中途放弃,岂不是太过可惜?
另附中国计算机学会的杰出会员、常务理事轩哥博士的B站视频讲解链接https://space.bilibili.com/518554541/?spm_id_from=333.999.0.0,供大家更好的进行学习与刷题~( ̄▽ ̄~)~
愿你的结局,配得上你一路的颠沛流离。