NOJ题目合集
1.求最值问题
1000ms 262144K
描述:
给定 NN 个整数 1≤N≤1001≤N≤100 ,求出这 NN 个数中的最大值,最小值。
输入:
多组数据,第一行为一个整数 NN ,第二行为 NN 个不超过 100100 的正整数,用空格隔开。
输出:
对每组数据输出一行,包含两个整数,用一个空格隔开,分别表示 NN 个数中的最大值和最小值。
样例输入:
5
4 6 7 3 1
4
4 3 5 1
样例输出:
7 1
5 1
注释:
以下为此题一个正确的答案(C++语言),大家可以参考,尤其是对于多组输入数据的读入方式。
#include <cstdio>
const int N = 101;
int main()
{
int a[N];
int n,i,max,min;
while(scanf("%d",&n)==1)
{
max = -1,min = 101;
for(i=1;i<=n;i++)
{
scanf("%d",&a[i]);
if(a[i]>max) max = a[i];
if(a[i]<min) min = a[i];
}
printf("%d %d\n",max,min);
}
return 0;
}
本题来源于南京邮电大学在线测评系统。
标准答案:
`int main() {`
`int N;`
`while (scanf("%d", &N) != EOF) {`
`int num, max, min;`
`scanf("%d", &num);`
`max = min = num;`
`for (int i = 1; i < N; ++i) {`
`scanf("%d", &num);`
`if (num > max) max = num;`
`if (num < min) min = num;`
`}`
`printf("%d %d\n", max, min);`
`}`
`return 0;`
`}`
2.新对称素数问题
1000ms 262144K
描述:
判断一个数是否为对称且不大于五位数的素数。
输入:
输入数据两行,第一行一个整数nn,满足1<n<601<n<60。
第二行有nn个的正整数xx (0<x<232)(0<x<232),以空格分隔。
输出:
对于每个x,如果该数是不大于五位数的对称素数,则输出“Yes”,否则输出“No”。每个判断结果单独列一行。
样例输入:
3
11 101 272
样例输出:
Yes
Yes
No
注释:
请注意Yes和No首字母需要大写。
本题来源于南京邮电大学在线测评系统。
标准答案:
#include <stdio.h>`
`\#include <string.h>`
`\#include <math.h>`
`// 判断是否为素数`
`int isPrime(int num) {`
if (num <= 1) return 0;
if (num == 2) return 1;
if (num % 2 == 0) return 0;
for (int i = 3; i <= sqrt(num); i += 2) {
if (num % i == 0) return 0;
}
return 1;
`}`
`// 判断是否为对称数`
`int isPalindrome(int num) {`
char str[6];
sprintf(str, "%d", num); // 将数字转换为字符串
int len = strlen(str);
for (int i = 0; i < len / 2; i++) {
if (str[i] != str[len - 1 - i]) return 0;
}
return 1;
`}`
`int main() {`
int n;
scanf("%d", &n); // 读取第一行的n
for (int i = 0; i < n; i++) {
int x;
scanf("%d", &x); // 读取第二行的每个数字
// 判断是否为不大于五位数的对称素数
if (x > 99999) {
printf("No\n");
} else if (isPrime(x) && isPalindrome(x)) {
printf("Yes\n");
} else {
printf("No\n");
}
}
return 0;
`}
3.进制转换
1000ms 262144K
描述:
将一个十进制数N转换成R进制数输出,2≤R≤16,R≠10。
输入:
多行。第一行指出以下一共有多少组数据,后续每行包含两个整数N和R,以空格分隔,-100000≤N≤100000,2≤R≤16,R≠10。
输出:
多行。每行给出转换后的R进制数。
样例输入:
3
7 2
23 12
-4 3
样例输出:
111
1B
-11
注释:
本题来源于南京邮电大学在线测评系统。
标准答案:
#include <stdio.h>
void decimal_to_r(int n, int r) {
if (n == 0) {
printf("0\n");
return;
}
char digits[32];
int index = 0;
int is_negative = n < 0;
if (is_negative) n = -n;
while (n > 0) {
digits[index++] = "0123456789ABCDEF"[n % r];
n /= r;
}
if (is_negative) printf("-");
for (int i = index - 1; i >= 0; i--) {
putchar(digits[i]);
}
printf("\n");
}
int main() {
int t, n, r;
scanf("%d", &t);
while (t--) {
scanf("%d %d", &n, &r);
decimal_to_r(n, r);
}
return 0;
}
4.最大公约数和最小公倍数
1000ms 262144K
描述:
求两个正整数的最大公约数和最小公倍数
输入:
两个正整数A,B
输出:
两个正整数的最大公约数、最小公倍数
样例输入:
4 3
样例输出:
1 12
注释:
本题来源于南京邮电大学在线测评系统。
标准答案:
#include<iostream>
\#include<algorithm>
using namespace std;
int main(){
int x,y;
cin>>x>>y;
int a=__gcd(x,y);
int b=(x*y)/a;
cout<<a<<' '<<b<<endl;
return 0;
}
5.斐波那契数列
1000ms 262144K
描述:
在数学上,斐波那契数列(Fibonacci Sequence),是以递归的方法来定义:
F0=0F0=0
F1=1F1=1
Fn=Fn−1+Fn−2Fn=Fn−1+Fn−2
用文字来说,就是斐波那契数列由0和1开始,之后的斐波那契数就由之前的两数相加。首几个斐波那契数是:
0,1,1,2,3,5,8,13,21,34,55,89,144,⋯0,1,1,2,3,5,8,13,21,34,55,89,144,⋯
特别指出:00不是第一项,而是第零项。
在西方,最先研究这个数列的人是比萨的列奥纳多(又名斐波那契),他描述兔子生长的数目时用上了这数列。
- 第一个月有一对刚诞生的兔子
- 第两个月之后它们可以生育
- 每月每对可生育的兔子会诞生下一对新兔子
- 兔子永不死去
假设在nn月有新生及可生育的兔子总共aa对,n+1n+1月就总共有bb对。在n+2n+2月必定总共有a+ba+b对:因为在n+2n+2月的时候,所有在nn月就已存在的aa对兔子皆已可以生育并诞下aa对后代;同时在前一月(n+1n+1月)之bb对兔子中,在当月属于新诞生的兔子尚不能生育。
现请求出斐波那契数列第nn项数值,0≤n≤400≤n≤40。
输入:
一个整数,表示斐波那契数列项数nn,0≤n≤400≤n≤40。
输出:
一个整数,表示斐波那契数列第nn项数值。
样例输入:
4
样例输出:
3
注释:
本题来源于南京邮电大学在线测评系统。
标准答案:
#include <bits/stdc++.h>
using namespace std;
int arr[40];
int main(){
int n=0;
scanf("%d",&n);
arr[0]=1;
arr[1]=1;
for(int i=2;i<n;i++){
arr[i]=arr[i-1]+arr[i-2];
}
printf("%d",arr[n-1]);
return 0;
}
6.回文回文
1000ms 262144K
描述:
回文是一种有趣的现象。英语中单词Palindromes指顺读倒读都一样的词语,比如radar,reviver,repaper,deified,rotator。美国南卡罗来那州查尔斯顿市北部有一片沼泽地,其名字的拼法也采用了这一形式:Wassamassaw,印第安语的意思是“世界上最恶劣的地方。
现在给定一个单词,要求你判断这个单词是不是回文词。
输入:
输入数据由包括一个字符串,字符串表示一个单词(长度为[1,256][1,256]),仅由字母组成,没有前导或后置的非法字符,单词后紧跟换行符(\n
)。
输出:
对于一个单词,如果是回文词,输出“Yes”,否则,输出“No”。
样例输入:
Wassamassaw
样例输出:
Yes
样例输入:
Wassamassam
样例输出:
No
注释:
请注意输出中Yes与No的大小写。
本题来源于南京邮电大学在线测评系统。
标准答案:
#include <bits/stdc++.h>
using namespace std;
int main() {
char word[257]; // 定义一个长度为257的字符数组,用于存储输入的单词(包括换行符)
gets(word); // 读取一行输入,包括换行符
int len = strlen(word);
// 判断是否为回文
int is_palindrome = 1; // 默认为回文
for (int i = 0, j = len - 1; i < j; i++, j--) {
if (toupper(word[i]) != toupper(word[j])) { // 忽略大小写进行比较
is_palindrome = 0;
break;
}
}
// 输出结果
if (is_palindrome) {
printf("Yes\n");
} else {
printf("No\n");
}
return 0;
}
7.萌萌摘苹果
1000ms 262144K
描述:
萌萌家的院子里有一棵苹果树,每到秋天树上就会结出一些苹果。苹果成熟的时候,萌萌就会跑去摘苹果。萌萌有个3030厘米高的板凳,当她不能直接用手摘到苹果的时候,就会踩到板凳上再试试。
现在已知树上所有苹果到地面的高度,以及萌萌把手伸直的时候能够达到的最大高度,请帮萌萌算一下她能够摘到的苹果的数目以及萌萌能否摘下所有的苹果。假设她碰到苹果,苹果就会掉下来。
输入:
输入包括三行数据。
第一行包含一个整数nn,表示树上的苹果总数,满足1≤n≤201≤n≤20。
第二行包含nn个整数a1⋯ana1⋯an分别表示这nn个苹果到地面的高度(以厘米为单位),满足100≤an≤200100≤an≤200,两个相邻的整数之间用一个空格隔开。
第三行只包括一个整数hh,满足100≤h≤120100≤h≤120,表示萌萌把手伸直的时候能够达到的最大高度(以厘米为单位)。
输出:
输出包括两行。
第一行包含一个整数,表示萌萌能够摘到的苹果的数目。
第二行为一个字符串Yes
或No
,如果陶陶能摘下树上所有苹果,请输出Yes
,如果不能,请输出No
。
样例输入:
10
100 200 150 140 129 134 167 198 200 111
110
样例输出:
5
No
样例输入:
2
100 110
120
样例输出:
2
Yes
注释:
- 请注意
Yes
与No
首字母大写。 - 对于第一组样例,萌萌不踩上凳子可以摘下第一个苹果,踩上凳子后可以摘下第四个、第五个、第六个和第十个苹果,合起来一共摘到5个苹果。
标准答案:
#include <bits/stdc++.h>
using namespace std;
const int N=25;
int a[N],n,h,cnt;
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
cin>>h;
for(int i=1;i<=n;i++){
if(h+30>=a[i]){
cnt++ ;
}
}
cout<<cnt<<endl;
cout<<(cnt==n?"Yes\n":"No\n");
return 0;
}
8.忠诚的骑士
1000ms 262144K
描述:
一位忠诚的骑士在战场上立下汗马功劳。
回到王都后,经济拮据的国王便许诺,将金币作为工资,发放给这位骑士,而骑士每天获得的金币会随着时间而增加。
第一天骑士收到一枚金币;之后两天(第二天和第三天),每天收到两枚金币;之后三天(第四、五、六天),每天收到三枚金币;之后四天,每天收到四枚金币,以此类推;这种工资发放模式会一直延续下去,当连续NN天收到NN枚金币后,骑士会在之后的N+1N+1天,每天收到N+1N+1枚金币。
请计算前KK天里,骑士一共获得了多少金币。
输入:
输入仅包含一个正整数KK,表示发放金币的天数,满足1≤K≤100001≤K≤10000。
输出:
输出仅包含一个正整数,即骑士收到的金币数。
样例输入:
6
样例输出:
14
样例输入:
1000
样例输出:
29820
注释:
对于第一个样例,骑士一共收到1+2+2+3+3+3=141+2+2+3+3+3=14枚金币。
标准答案:
#include <stdio.h>
int main(){
int K;
scanf("%d",&K);
int n=0;
while(n*(n+1)/2<K){
n++;
}
if(n*(n+1)/2>K){
n--;
}
int total_coins=n*(n+1)*(2*n+1)/6;
int remaining_days=K-n*(n+1)/2;
total_coins+=(n+1)*remaining_days;
printf("%d",total_coins);
}
9.最小质数合数之和问题
1000ms 262144K
描述:
查找大于正整数nn的最小质数和最小合数之和。
质数是指在大于11的自然数中,除了11和它本身以外不再有其他因数的自然数。
合数是指在大于11的整数中除了能被11和本身整除外,还能被其他数(00除外)整除的数。
输入:
一个正整数n,题目保证1≤n≤10000000001≤n≤1000000000。
输出:
一个正整数,表示大于正整数nn的最小质数和最小合数之和。
样例输入:
1
样例输出:
6
样例输入:
96
样例输出:
195
注释:
📝 本题为2021年南京邮电大学研究生复试上机原题。
对于第一组样例:nn为11的情况下,最小素数为22,最小合数为44,因此答案为2+4=62+4=6。
标准答案:
#include <bits/stdc++.h>
using namespace std;
bool is_prime(int num) {
if (num <= 1) return false;
if (num <= 3) return true;
if (num % 2 == 0 || num % 3 == 0) return false;
for (int i = 5; i * i <= num; i += 6) {
if (num % i == 0 || num % (i + 2) == 0) return false;
}
return true;
}
int main() {
int n;
scanf("%d", &n);
int next_prime = n + 1;
while (!is_prime(next_prime)) {
next_prime++;
}
int next_composite = n + 1;
while (is_prime(next_composite)) {
next_composite++;
}
int sum = next_prime + next_composite;
printf("%d\n", sum);
return 0;
}
10.级数求和
1000ms 262144K
描述:
已知:Sn=1+12+13+…+1nSn=1+12+13+…+1n。显然对于任意一个整数 kk,当 nn 足够大的时候,Sn>kSn>k。
现给出一个整数 kk,要求计算出一个最小的 nn,使得 Sn>kSn>k。
输入:
一个正整数 kk,题目保证 1≤k≤151≤k≤15。
输出:
一个正整数 nn,表示满足 Sn>kSn>k 的最小 nn 值。
样例输入:
1
样例输出:
2
标准答案:
#include <stdio.h>
int main() {
int k; // 输入的整数k
scanf("%d", &k); // 读取输入
double S_n = 0.0; // 用于存储Sn的值
int n = 1; // 从n=1开始
// 循环计算Sn,直到Sn > k
while (S_n <= k) {
S_n += 1.0 / n; // 将1/n加到Sn中
n++; // n自增
}
// 输出结果,注意n在循环结束时多加了1,所以输出n-1
printf("%d\n", n - 1);
return 0;
}
11.小明喝可乐
1000ms 262144K
描述:
小明是个可乐重度爱好者,平日里没事就喜欢喝可乐。今天,他最喜欢喝的崂山可乐(小明是个狠人)更新了可乐瓶换可乐活动,即每集齐 kk 个可乐瓶,则赠送 11 瓶免费的可乐。
现在,小明正好手上有 nn 瓶可乐,他想知道他最多能够喝多少瓶,可是他编程水平不如你,所以他想请你帮他写个程序算一下。
输入:
输入共一行,包含两个整数 nn 和 kk,分别表示小明手上的可乐数量和满赠活动中每多少个可乐瓶可以获得一瓶免费的可乐。
题目保证 1<n,k≤1081<n,k≤108 。
输出:
输出共一行一个整数,表示小明能够喝到的可乐数量。
样例输入:
10 3
样例输出:
14
注释:
对于第一组样例,小明可以先喝 1010 瓶可乐,然后拿其中 99 个可乐瓶去换 33 瓶新的可乐喝,最后再拿新的 33 瓶可乐再换一瓶新的,一共喝了 10+3+1=1410+3+1=14 瓶。
【温馨提示:这不是脑经急转弯,小明不可以借可乐瓶,也不可以花钱另外买可乐喝。】
标准答案:
#include <bits/stdc++.h>
using namespace std;
int main(){
int n,k;
scanf("%d %d",&n,&k);
int total_bottles=n;
int empty_bottles=n;
while(empty_bottles>=k){
int new_bottles=empty_bottles/k;
total_bottles+=new_bottles;
empty_bottles=empty_bottles%k+new_bottles;
}
printf("%d\n",total_bottles);
return 0;
}
12.华强种瓜
1000ms 131072K
描述:
华强买到了不保熟的瓜,他很生气,遂决定……
自己种瓜!
第二天,华强承包了一大片瓜田,他买来了 n^2个保熟的西瓜种子,并且严格按照一个 n×n 米间距的网格进行种植。为了方便华强记忆,这个网格的坐标从 1 开始编号,到 n 结束。
为了让瓜保熟,他又买来了 k 个洒水器,洒水器工作半径为 r 米,安装在在网格中的某些种子的正上方。
安装完这些洒水器后,华强很想知道现在他的瓜里面有多少能够被撒到水。
输入:
输入共包含 n+k 行。
第一行包含 3 个整数 n、k 和 r,分别表示网格边距、洒水器数量和洒水器工作半径,题目保证 1≤n,k≤200。
接下来 k 行,每行两个整数 x 和 y,表示每个洒水器在网格中的坐标 (x,y)
输出:
一行一个整数,表示被洒水器覆盖到的西瓜总数。
样例输入:
5 2 1
3 3
4 2
样例输出:
8
注释:
对于第一组样例,(3,3) 上的洒水器工作半径可以覆盖到 (3,3) (4,3) (2,3) (3,2) (3,4) 的瓜。而 (4,2) 上的洒水器可以覆盖到 (4,2)(5,2) (3,2) (4,1) (4,3) 的瓜。去重后,共有 8 个瓜被覆盖到。
标准答案:
#include <stdio.h>
\#include <math.h>
int main(){
int n,k,r;
scanf("%d %d %d",&n,&k,&r);
int covered[n+1][n+1];
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
covered[i][j]=0;
}
}
for(int i=0;i<k;i++){
int x,y;
scanf("%d %d",&x,&y);
//计算覆盖范围
for(int dx=-r;dx<=r;dx++){
for(int dy=-r;dy<=r;dy++){
int nx=x+dx,ny=y+dy;
if(1<=nx&&nx<=n&&1<=ny&&ny<=n&&dx*dx+dy*dy<=r*r){
covered[nx][ny]=1;
}
}
}
}
int total_cover=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(covered[i][j]==1){
total_cover++;
}
}
}
printf("%d\n",total_cover);
return 0;
}
13.天子与诸侯
1000ms 262144K
描述:
在周朝,天子分天下而诸侯治天下,但维持诸侯均势是一个令人头痛的问题。
位于镐京的周天子等人开创性的提出,当周天子直属军队的军力 大于等于 诸侯中军力前三之和的时候,便可保诸侯均势,天下太平。
现在,周天子手上收集了所有诸侯国的军力数据,希望你能告诉他周天子的军队至少需要多少军力才能维持诸侯均势。
输入:
输入数据共包含两行。
第一行一个整数 nn,表示诸侯国数量,题目保证 3≤n≤10003≤n≤1000。
第二行 nn 个整数 P1,P2,…,PnP1,P2,…,Pn,分别表示每个诸侯国的军力 pp,题目保证 0≤p≤1e80≤p≤1e8。
输出:
一行一个整数,表示周天子维持诸侯均势的最少军力。
样例输入:
6
12 9 6 100 0 4
样例输出:
121
样例输入:
10
0 0 0 0 0 0 0 0 0 0
样例输出:
0
样例输入:
10
0 0 0 1 9 8 63 0 9 1
样例输出:
81
注释:
对于第一组样例,军力前三的诸侯分别拥有 100100,1212 和 99 军力,周天子至少需要 121121 军力维持均势。
对于第二组样例,军力前三的诸侯都只有 00 军力,因此周天子无需一兵一卒, 00 军力就能维持均势。
关于测试数据:
题目保证,对于 20%20% 的测试数据, n=3n=3;
题目保证,对于 40%40% 的测试数据,P1,P2,…,PnP1,P2,…,Pn 将以降序或升序给出。
标准答案:
#include <bits/stdc++.h>
using namespace std;
int compare(const void *a,const void *b){
return (*(int *)b-*(int *)a);
}
int main(){
int n;
scanf("%d",&n);
int p[n];
for(int i=0;i<n;i++){
scanf("%d",&p[i]);
}
qsort(p,n,sizeof(int),compare);
int sum=p[0]+p[1]+p[2];
printf("%d\n",sum);
return 0;
}
14.矩阵变换问题
1000ms 262144K
描述:
给定一个 n×mn×m 的矩阵,对于 初始矩阵 中所有值为 11 的元素,重置其 所在行列 的所有元素为 00,最后输出整个修改后的矩阵。
输入:
输入共包含 1+n1+n 行。
第一行包两个整数 nn 和 mm, 分别表示矩阵的长和宽,题目保证 2≤n,m≤7002≤n,m≤700 且 4≤n×m≤1800004≤n×m≤180000。
接下来 nn 行,每行包含 mm 个整数,第 ii 行第 jj 个整数表示矩阵中坐标 (i,j)(i,j) 的值 Ai,jAi,j,题目保证 0≤Ai,j≤1e80≤Ai,j≤1e8。
输出:
输出共包含 nn 行,每行包含空格分隔 mm 个整数。
第 ii 行第 jj 个整数表示修改后的矩阵中坐标 (i,j)(i,j) 的值 Ai,jAi,j。
请注意输出中每行行末最后一个数字后面紧跟换行符,不能包含空格。
样例输入:
3 3
3 4 5
0 1 2
6 7 8
样例输出:
3 0 5
0 0 0
6 0 8
样例输入:
3 4
1 2 3 1
4 5 6 7
8 9 10 11
样例输出:
0 0 0 0
0 5 6 0
0 9 10 0
注释:
关于测试数据:
题目保证,对于 115115 的测试数据, n=4,m=4n=4,m=4;
题目保证,对于 1313 的测试数据,2≤n,m≤1002≤n,m≤100。
题目保证,对于 2323 的测试数据,2≤n≤1002≤n≤100 或 2≤m≤1002≤m≤100。
标准答案:
#include <bits/stdc++.h>
using namespace std;
int main(){
int n,m;
scanf("%d %d",&n,&m);
int matrix[n][m];
int row[n];
int col[m];
for(int i=0;i<n;i++){
row[i]=0;
}
for(int j=0;j<m;j++){
col[j]=0;
}
//读取矩阵
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
scanf("%d",&matrix[i][j]);
if(matrix[i][j]==1){
row[i]=1;
col[j]=1;
}
}
}
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(row[i]==1||col[j]==1){
matrix[i][j]=0;
}
}
}
// 输出修改后的矩阵
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
printf("%d", matrix[i][j]);
if (j < m - 1) {
printf(" "); // 行内元素之间用空格分隔
}
}
printf("\n"); // 每行结束后换行
}
return 0;
}
15.小明的记忆游戏
1000ms 262144K
描述:
小明最近被拉去参加了一场记忆游戏,主持人会给小明一些数字,小明需要记住这些数字,然后主持人会问小明某些数字是否出现在这些数字中,小明需要依次回答是或者否。
小明的记性不是很好,所以他想请你帮忙告诉他,某些数字是否出现在之前的数字中。
输入:
第一行一个整数 nn,表示主持人将要给出的数字,题目保证 1≤n≤1051≤n≤105。
第二行 nn 个整数 a1,a2,⋯,ana1,a2,⋯,an,表示主持人给出的每个数字 aa,题目保证 1≤a≤1091≤a≤109。
第三行一个整数 mm,表示主持人询问的次数,题目保证 1≤m≤1051≤m≤105。
接下来 mm 行,每行一个整数 b1,b2,⋯,bnb1,b2,⋯,bn,表示主持人询问的每个数字 bb,题目保证 1≤b≤1091≤b≤109。
输出:
输出 mm 行,每行一个字符串,如果第 ii 行的数字 bibi 出现在之前的数字中,输出 YES
,否则输出 NO
,全部大写。
样例输入:
5
1 2 3 4 5
5
1
2
3
3
56
样例输出:
YES
YES
YES
YES
NO
样例输入:
7
9 52355 3 7 76 223 1
2
23423
3
样例输出:
NO
YES
注释:
题目保证,对于 20%20% 的数据,有 m=1m=1。
题目保证,对于 40%40% 的数据,有 n=1n=1。
题目保证,对于 100%100% 的数据,有 1≤n,m≤1051≤n,m≤105,1≤a,b≤1091≤a,b≤109。
请仔细评估提交代码的算法复杂度。
标准答案:
n=int(input())
numbers=set(map(int,input().split()))
m=int(input())
for _ in range(m):
b=int(input());
if b in numbers:
print("YES")
else:
print("NO")
16.小明算树
1000ms 262144K
描述:
小明家住在一条长为 ll 的马路的一边,马路上有一排树,每两棵相邻的树之间的间隔都是 11 米。我们可以把马路看成一个数轴,马路的一端在数轴 00 的位置,另一端在 ll 的位置;数轴上的每个整数点,即 0,1,2,…,l0,1,2,…,l,都种有一棵树。
最近,由于道路拓宽和地铁建设,马路上一些区域要用来建地铁。这些区域用它们在数轴上的起始点和终止点表示。已知任一区域的起始点和终止点的坐标都是整数,区域之间可能有重合的部分。
现在施工单位要把这些区域中的树(包括区域端点处的两棵树)移走,而好奇的小明想知道将这些树都移走后,马路上还有多少棵树。
输入:
第一行两个整数,分别表示马路的长度 ll 和区域的数目 mm,题目保证 1≤l≤1041≤l≤104,1≤m≤1001≤m≤100。
接下来 mm 行,每行两个整数 u,vu,v,表示一个区域的起始点和终止点的坐标,题目保证 0≤u≤v≤l0≤u≤v≤l。
输出:
输出一行,共一个整数,表示将这些树都移走后,马路上剩余的树木数量。
样例输入:
500 3
150 300
100 200
470 471
样例输出:
298
注释:
题目保证,对于 1313 的数据,区域之间没有重合。
题目保证,对于 100%100% 的数据,有 1≤l≤1041≤l≤104,1≤m≤1001≤m≤100,0≤u≤v≤l0≤u≤v≤l。
标准答案:
#include <stdio.h>
\#include <stdlib.h>
\#include <string.h>
int main() {
int l, m;
scanf("%d %d", &l, &m); // 读取马路长度和区域数目
// 初始化布尔数组,标记哪些位置的树木需要移除
int *removed = (int *)calloc(l + 1, sizeof(int)); // 默认全部初始化为0
if (removed == NULL) {
printf("Memory allocation failed\n");
return -1;
}
// 读取每个区域并标记需要移除的树木
for (int i = 0; i < m; i++) {
int u, v;
scanf("%d %d", &u, &v); // 读取区域的起始点和终止点
for (int j = u; j <= v; j++) {
removed[j] = 1; // 标记这些位置的树木需要移除
}
}
// 统计移除的树木数量
int removed_count = 0;
for (int i = 0; i <= l; i++) {
if (removed[i] == 1) {
removed_count++;
}
}
// 计算剩余的树木数量
int remaining_trees = l + 1 - removed_count;
// 输出结果
printf("%d\n", remaining_trees);
// 释放内存
free(removed);
return 0;
}
17.小明的抽奖游戏
1000ms 262144K
描述:
小明组织了一场抽奖游戏,他给每个参加抽奖的人都发放了一张写有幸运数字的卡片,之后,他会用一套系统随机抽出一些中奖数字,中奖数字为任意幸运数字因数的人将获得奖品。现在,他想知道,一共有多少人将会获得奖品。
输入:
第一行一个整数 nn,表示参加抽奖的人数,题目保证 1≤n≤1051≤n≤105。
第二行 nn 个整数 a1,a2,⋯,ana1,a2,⋯,an,表示每个人的幸运数字 aa,题目保证 1≤a≤1091≤a≤109。
第三行一个整数 mm,表示系统将要抽出的中奖数字个数,题目保证 1≤m≤1021≤m≤102。
接下来 mm 行,每行一个整数 b1,b2,⋯,bnb1,b2,⋯,bn,表示系统抽出的每个中奖数字 bb,题目保证 1≤b≤1091≤b≤109。
输出:
输出一行,共一个整数,表示总获奖人数。
样例输入:
6
6 1 2 3 4 6
2
3
4
样例输出:
4
样例输入:
5
14 17 12 97 40
2
4
3
样例输出:
2
注释:
题目保证,对于 20%20% 的数据,有 m=1m=1。
题目保证,对于 40%40% 的数据,有 n=1n=1。
题目保证,对于 100%100% 的数据,有 1≤n≤1051≤n≤105,1≤m≤1021≤m≤102,1≤a,b≤1091≤a,b≤109。
标准答案:
#include <stdio.h>
\#define MAX_N 100005
\#define MAX_M 100
int main(){
int n,m;
int luckynumbers[MAX_N];
int winningNumbers[MAX_M];
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d",&luckynumbers[i]);
}
scanf("%d",&m);
for(int j=0;j<m;j++){
scanf("%d",&winningNumbers[j]);
}
int totalNumbers=0;
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(winningNumbers[j]%luckynumbers[i]==0){
totalNumbers++;
break;
}
}
}
printf("%d\n",totalNumbers);
return 0;
}
18.小明算分
1000ms 262144K
描述:
小明组织了一场写作比赛,共有 nn 名同学参加他组织的写作比赛。
小明邀请了 mm 名评委的评分,评分范围是 00 到 1010 分。而每位同学的得分就是这些评委给分中去掉一个最高分,去掉一个最低分,剩下 m−2m−2 个评分的平均数。
小明想知道得分最高的同学分数是多少,所以他想请你帮忙告诉他,最终评分保留 22 位小数。
输入:
第一行两个整数 n,mn,m,表示参加写作比赛的同学数量和评委的数量,题目保证 1≤n≤100,3≤m≤201≤n≤100,3≤m≤20。
接下来 nn 行,每行 mm 个整数 s1,s2,⋯,sms1,s2,⋯,sm,表示每位评委对某位同学的具体打分 ss,题目保证 0≤s≤100≤s≤10。
输出:
第一行一个浮点数,输出最终评分最高的同学的分数,保留两位小数。
样例输入:
7 6
4 7 2 6 10 7
0 5 0 10 3 10
2 6 8 4 3 6
6 3 6 7 5 8
5 9 3 3 8 1
5 9 9 3 2 0
5 8 0 4 1 10
样例输出:
6.00
注释:
题目保证,对于 1313 的数据,有 m=3m=3。
题目保证,对于 100%100% 的数据,有 1≤n≤100,3≤m≤20,0≤s≤101≤n≤100,3≤m≤20,0≤s≤10。
标准答案:
#include <stdio.h>
\#include <stdlib.h>
// 函数:计算去掉一个最高分和一个最低分后的平均分
double calculateScore(int *scores, int m) {
int maxScore = 0, minScore = 10;
int sum = 0;
// 找到最高分和最低分,并计算总分
for (int i = 0; i < m; i++) {
if (scores[i] > maxScore) maxScore = scores[i];
if (scores[i] < minScore) minScore = scores[i];
sum += scores[i];
}
// 去掉一个最高分和一个最低分
sum -= (maxScore + minScore);
// 计算平均分
return (double)sum / (m - 2);
}
int main() {
int n, m;
scanf("%d %d", &n, &m); // 输入参赛人数和评委人数
double highestScore = -1.0; // 初始化最高分数为一个不可能的负值
for (int i = 0; i < n; i++) {
int scores[m]; // 存储每位评委的打分
for (int j = 0; j < m; j++) {
scanf("%d", &scores[j]); // 输入每位评委的打分
}
// 计算当前同学的最终得分
double currentScore = calculateScore(scores, m);
// 更新最高分数
if (currentScore > highestScore) {
highestScore = currentScore;
}
}
// 输出最高分数,保留两位小数
printf("%.2f\n", highestScore);
return 0;
}
19.开普勒星球历法
1000ms 262144K
描述:
开普勒星的公转周期略长于地球,因此,开普勒星人将一个开普勒年分为 426426 天。其中,前十二个月和地球完全一致,1313 月和 1414 月则分别为 3030 和 3131 天。
- 1月 31天
- 2月 28天(闰年29天)
- 3月 31天
- 4月 30天
- 5月 31天
- 6月 30天
- 7月 31天
- 8月 31天
- 9月 30天
- 10月 31天
- 11月 30天
- 12月 31天
- 13月 30天
- 14月 31天
每过几个开普勒年,就会有一个闰年,闰年的 22 月有 2929 天。具体来说,如果一个开普勒年:
- 是整百年:要被 400400 整除才是闰年,否则不是闰年;
- 是非整百年:只要被 44 整除就是闰年,否则不是闰年。
例如,19001900 年是平年,20002000 年是闰年,20202020 年是闰年,20232023 年是平年。
现在,开普勒星人想知道,从开普勒星今年的第一天开始,第 nn 天是几月几日。
输入:
输入共一行,包含两个整数 YY 和 nn,分别表示今年的年份和需要计算的跨越天数,题目保证 1234≤Y≤99991234≤Y≤9999,1≤n≤4261≤n≤426。
输出:
输出共一行,包含两个整数,分别表示第 nn 天是几月几日。
样例输入:
2023 1
样例输出:
1 1
样例输入:
2024 426
样例输出:
14 30
样例输入:
2000 60
样例输出:
2 29
注释:
对于 20%20% 的数据,题目保证 n≤59n≤59。
对于 20%20% 的数据,题目保证 Y=2023Y=2023。
对于 50%50% 的数据,题目保证 YY 为非闰年。
对于 100%100% 的数据,题目保证 1234≤Y≤99991234≤Y≤9999,1≤n≤4261≤n≤426。
标准答案:
#include <stdio.h>
int days_in_month[15] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 30, 31};
int isLeapYear(int year){
if(year%400==0||(year%4==0&&year%100!=0)){
return 1;
}
return 0;
}
int main(){
int Y,n;
scanf("%d %d",&Y,&n);
if(isLeapYear(Y)){
days_in_month[2]=29;
}
int month=1;
int day=n;
while(day>days_in_month[month]){
day-=days_in_month[month];
month++;
}
printf("%d %d\n",month,day);
return 0;
}
20.房屋装修
1000ms 262144K
描述:
小明家的院子里有一块矩形的泥坑,趁着这次房屋装修,小明想要用正方形的瓷砖整齐排列,把泥坑完全掩盖起来。
小明想要知道,最少需要多少块瓷砖才能做到,这样他才好去拼多多上买。
输入:
输入共一行,包含三个整数 nn, mm 和 aa。
nn 与 mm 表示泥地的两条边长,aa 表示正方形瓷砖的边长,题目保证,1≤n,m,a≤1081≤n,m,a≤108。
输出:
输出共一行,包含一个整数,表示最少需要的瓷砖数量。
样例输入:
6 6 4
样例输出:
4
样例输入:
4 7 4
样例输出:
2
注释:
题目保证,对于 20%20% 的数据,有 n=an=a。
题目保证,对于 20%20% 的数据,有 n=1n=1 或者 m=1m=1。
题目保证,对于 20%20% 的数据,有 n=mn=m。
题目保证,对于 80%80% 的数据,有 1≤n,m,a≤1041≤n,m,a≤104。
题目保证,对于 100%100% 的数据,有 1≤n,m,a≤1081≤n,m,a≤108。
标准答案:
#include <stdio.h>
long long min_tiles(int n, int m, int a) {
long long rows = (n + a - 1) / a; // 计算需要的行数,向上取整
long long cols = (m + a - 1) / a; // 计算需要的列数,向上取整
return rows * cols; // 总瓷砖数为行数乘以列数
}
int main() {
int n, m, a;
scanf("%d %d %d", &n, &m, &a);
printf("%lld\n", min_tiles(n, m, a));
return 0;
}
21.最长连续上升子序列
1000ms 262144K
描述:
给定一个长度为 nn 的整数序列 a1,a2,⋯,ana1,a2,⋯,an,求最长的连续上升子序列的长度。
连续上升子序列可以由两个下标 ll 和 rr (l≤rl≤r)确定,如果对于每个 l≤i<rl≤i<r,都有 ai<ai+1ai<ai+1,那么子序列 al,al+1,⋯,aral,al+1,⋯,ar 就是一个连续上升子序列。
输入:
第一行包含一个整数 nn,表示序列的长度,题目保证 1≤n≤1041≤n≤104。
第二行包含 nn 个整数 a1,a2,⋯,ana1,a2,⋯,an,表示给定的整数序列,题目保证 −109≤ai≤109−109≤ai≤109。
输出:
输出一个整数,表示最长的连续上升子序列的长度。
样例输入:
5
1 3 5 4 7
样例输出:
3
样例输入:
5
2 2 2 2 2
样例输出:
1
注释:
题目保证,对于 20%20% 的数据,序列中仅包含一组连续上升子序列。
题目保证,对于 20%20% 的数据,有 1≤n≤1021≤n≤102。
题目保证,对于 60%60% 的数据,有 1≤n≤1031≤n≤103。
题目保证,对于 100%100% 的数据,有 1≤n≤1041≤n≤104,−109≤ai≤109−109≤ai≤109。
标准答案:
#include <stdio.h>
int main() {
int n;
scanf("%d", &n);
int a[n];
for (int i = 0; i < n; i++) {
scanf("%d", &a[i]);
}
if (n == 0) {
printf("0\n");
return 0;
}
int max_length = 1;
int current_length = 1;
for (int i = 1; i < n; i++) {
if (a[i] > a[i-1]) {
current_length++;
if (current_length > max_length) {
max_length = current_length;
}
} else {
current_length = 1;
}
}
printf("%d\n", max_length);
return 0;
}
22.社交网络
1000ms 262144K
描述:
💡 (如果考生对完整解答本题与下一题没有足够把握,可以尝试只解决本题的一到几个特定数据范围,特定数据范围相较完整版更为简单,详见注释。)
《社交网络》是一部上映于2010年的电影,讲述了一个关于社交网络的故事。在这个故事中,马克·扎克伯格(Mark Zuckerberg)在哈佛大学宿舍中创立了Facebook,这个社交网络最终成为了全球最大的社交网络之一。
在 Facebook 数据库中,用户是一个个数字代码,而好友是用一条条记录来表示的。例如,如果 A 是 B 的好友,那么在数据库中就会有一条记录 (A, B)
。一旦出现了 (A, B)
,那么 (B, A)
就不会再出现, (A, B)
也不会再出现第二次。
现在,马克想要知道社交网络中拥有最多好友的人到底有多少好友。请你帮助马克编写一个程序,来统计社交网络中拥有最多好友的人的好友数量。
输入:
输入的第一行包含一个整数 nn,表示数据库中的数据总数,题目保证 1≤n≤1041≤n≤104 。
接下来 nn 行,每行包含两个整数 aiai 与 bibi,表示代码为 aiai 的用户与代码为 bibi 的用户之间存在好友关系,题目保证 1≤ai,bi≤1091≤ai,bi≤109 且 ai≠biai≠bi,同时题目保证用户数量不超过 10241024。
输出:
输出一个整数,表示社交网络中拥有最多好友的人的好友数量。
样例输入:
4
1 2
2 3
3 1
4 1
样例输出:
3
样例输入:
1
3 9
样例输出:
1
样例输入:
5
77 2
53 78
1 2
2 3
9 7
样例输出:
3
注释:
第一组样例中,用户 11 有 33 个好友,因此答案为 33。
题目保证,对于 10%10% 的数据,n=1n=1。
题目保证,对于 50%50% 的数据,aiai 已经预先按照升序排列给出。
题目保证,对于 60%60% 的数据,对于每一条关系,都有 ai<biai<bi。
题目保证,对于 80%80% 的数据,1≤ai,bi≤1051≤ai,bi≤105。
题目保证,对于 100%100% 的数据,1≤n≤1041≤n≤104 且 1≤ai,bi≤1091≤ai,bi≤109 且 ai≠biai≠bi。
标准答案:
#include <bits/stdc++.h>
using LL=long long;
using namespace std;
const int N=1e4+7;
int n,a[N];
unordered_map<LL,LL>mp;
signed main(){
cin>>n;
while(n--){
int a,b;
cin>>a>>b;
mp[a]++,mp[b]++;
}
LL res=0;
for(auto[k,v]:mp){
res=max[k,v]
}
cout<<res<<endl;
}
23.极速狂飙
1000ms 262144K
描述:
💡 (如果考生对完整解答本题与下一题没有足够把握,可以尝试只解决本题的一到几个特定数据范围,特定数据范围相较完整版更为简单,详见注释。)
《GT赛车:极速狂飙》是一部2023年美国传记运动剧情片,改编自PlayStation工作室的同名电子游戏系列。影片中,在市场主管丹尼·摩尔的提议下,日产汽车的赛车部门决定成立GT学院,目的是从赛车模拟游戏《GT赛车系列》中挑选有才华的玩家,并将他们训练成为真正的赛车手。
现在,第一场比赛的成绩已经出来了,请根据赛车手的各自耗时,计算出他们的名次,并给出最快完成比赛的前三名车手。
输入:
输入的第一行包含一个整数 nn,表示车手的数量,3≤n≤1003≤n≤100。
接下来 nn 行,每行包含一个整数 aiai,表示第 ii 个车手的总耗时(毫秒),1≤ai≤1e91≤ai≤1e9,题目保证不会出现相同的 aiai。
接下来 nn 行,每行包含一个字符串 bibi,表示第 ii 个车手的昵称,字符串长度小于 100100 且仅包含大小写字母(即A-Z,a-z,不包含标点、空格等),题目保证不会出现相同的选手昵称。
输出:
输出三行,每行包含一个字符串,分别表示第一、第二、第三名的车手的昵称。
样例输入:
3
15
14
13
Anaconda
Bootstrap
CentOS
样例输出:
CentOS
Bootstrap
Anaconda
样例输入:
4
7
13
4
246
DotNet
Erlang
FSharp
Golang
样例输出:
FSharp
DotNet
Erlang
注释:
题目保证,对于 40%40% 的数据,n=3n=3。
题目保证,对于 80%80% 的数据,所有的 aiai 已经预先按照升序或降序排列。
标准答案:
#include <stdio.h>
\#include <stdlib.h>
\#include <string.h>
\#define MAX_N 100
\#define NAME_LEN 100
typedef struct {
int time;
char name[NAME_LEN];
} Driver;
int compare(const void* a, const void* b) {
return ((Driver*)a)->time - ((Driver*)b)->time;
}
int main() {
int n;
scanf("%d", &n);
Driver drivers[MAX_N];
for (int i = 0; i < n; i++) {
scanf("%d", &drivers[i].time);
}
for (int i = 0; i < n; i++) {
scanf("%s", drivers[i].name);
}
qsort(drivers, n, sizeof(Driver), compare);
for (int i = 0; i < 3; i++) {
printf("%s\n", drivers[i].name);
}
return 0;
}
24.灰猎犬号
1000ms 262144K
描述:
《灰猎犬号》是一部 2020 年在 Apple TV+ 上映的战争历史片,由艾伦·史耐德执导,汤姆·汉克斯编剧。电影改编自C·S·佛雷斯特的 1955 年小说《杰出牧羊人》。影片讲述二战初期,由 37 支盟军船只组成的护航舰队在欧内斯特·克劳斯舰长率领的一艘驱逐舰指挥下,穿越险恶的北大西洋,同时还要与德国U型潜艇狼群的周旋。
在凶险的大西洋上,为了保护船队的安全,海军绘制了详细的海图,用于避开暗礁。在海图上,所有高于海平面的坐标都用数字 11 表示,而低于海平面的坐标都用数字 00 表示,上下左右相邻的一整块联通区域被认为是一座暗礁。
现在,你需要统计海图上一共有几座暗礁,以便更好地保护船队的安全。
输入:
第一行为两个整数 RR 和 CC,分别表示海图的行数和列数,题目保证,1≤R,C≤10001≤R,C≤1000。
接下来 RR 行,每行 CC 个数字 00 或 11,表示海图的具体内容。11 表示当前坐标高于海平面,00 表示低于海平面。
输出:
输出一个整数,表示海图上一共有几座暗礁。
样例输入:
6 8
1 0 0 0 0 1 0 1
1 1 0 0 0 0 0 1
1 1 1 0 0 0 0 1
0 0 0 0 0 0 0 1
1 0 0 0 1 0 0 1
1 0 0 1 0 0 0 1
样例输出:
6
注释:
题目保证,对于 20%20% 的数据,R=1R=1。
题目保证,对于 40%40% 的数据,所有暗礁仅由 11 个区块构成。
题目保证,对于 40%40% 的数据,R,C≤3R,C≤3。
题目保证,对于 100%100% 的数据,1≤R,C≤10001≤R,C≤1000,所有暗礁至多由 4848 个区块构成。
标准答案:
#include <bits/stdc++.h>
\#define MAX_R 1000
\#define MAX_C 1000
int map[MAX_R][MAX_C];
int visit[MAX_R][MAX_C];
int R,C;
void dfs(int i,int j){
if(i<0||i>=R||j<0||j>=C||map[i][j]!=1||visit[i][j]){
return;
}
visit[i][j]=1;
dfs(i+1,j);
dfs(i-1,j);
dfs(i,j+1);
dfs(i,j-1);
}
int main(){
scanf("%d %d",&R,&C);
for(int i=0;i<R;i++){
for(int j=0;j<C;j++){
scanf("%d",&map[i][j]);
}
}
int count=0;
for (int i = 0; i < R; i++) {
for (int j = 0; j < C; j++) {
if (map[i][j] == 1 && !visit[i][j]) {
count++;
dfs(i, j);
}
}
}
printf("%d\n", count);
return 0;
}
25.拿破仑传
1000ms 262144K
描述:
《拿破仑传》是一部2023年美国史诗时代电影,由雷德利·斯科特执导,大卫·史卡帕编剧,杰昆·菲尼克斯领衔主演;菲尼克斯亦身兼监制。电影以法国著名军事家、政治家和改革家拿破仑·波拿巴的故事为背景,讲述拿破仑从普通军官到一代帝王,最终兵败滑铁卢黯然退出历史舞台的人生经历,以及他与皇后约瑟芬之间的爱情故事。
现在,拿破仑正在领兵出战,他的粮草最多可以支撑一定数量的士兵,但从各个军团来的士兵数量不同,且军团不可进一步分割。请你帮助拿破仑计算出他最多可以领兵出战的数量。
输入:
输入的第一行包含两个整数 nn 和 CC,表示军团的数量和粮草最大支撑的士兵数量,题目保证,1≤n≤301≤n≤30,1≤C≤200001≤C≤20000。
接下来 nn 行,每行包含一个整数 mimi,表示第 ii 个军团的士兵数量,1≤mi≤1041≤mi≤104。
输出:
输出一行,包含一个整数,表示拿破仑最多可以领兵出战的数量。
样例输入:
6 24
8
3
12
7
9
7
样例输出:
24
注释:
对于第一组样例,拿破仑最多可以领兵出战的数量为 2424:第 11 个不选,第 22 个选,第 33 个选,第 44 个不选,第 55 个选,第 66 个不选,答案为 3+12+9=243+12+9=24。
题目保证,对于 20%20% 的数据点,n≤3n≤3。
题目保证,对于 20%20% 的数据点,每一个 mimi 的值完全相同。
题目保证,对于 40%40% 的数据点,mimi 以升序或降序给出。
题目保证,对于 80%80% 的数据点,n≤15n≤15。
题目保证,对于 100%100% 的数据点,1≤n≤301≤n≤30,1≤C≤200001≤C≤20000,1≤mi≤1041≤mi≤104。
标准答案:
#include <stdio.h>
\#include <stdlib.h>
int main() {
int n, C;
scanf("%d %d", &n, &C);
int *m = (int *)malloc(n * sizeof(int));
for (int i = 0; i < n; i++) {
scanf("%d", &m[i]);
}
int *dp = (int *)calloc(C + 1, sizeof(int));
for (int i = 0; i < n; i++) {
for (int j = C; j >= m[i]; j--) {
if (dp[j - m[i]] + m[i] > dp[j]) {
dp[j] = dp[j - m[i]] + m[i];
}
}
}
printf("%d\n", dp[C]);
free(m);
free(dp);
return 0;
}