New Online Judge 做题网站
试题 A: 排列字母
本题总分:
5
分
【问题描述】
小蓝要把一个字符串中的字母按其在字母表中的顺序排列。
例如,
LANQIAO
排列后为
AAILNOQ
。
又如,
GOODGOODSTUDYDAYDAYUP
排列后为
AADDDDDGGOOOOPSTUUYYY
。
请问对于以下字符串,排列之后字符串是什么?
WHERETHEREISAWILLTHEREISAWAY
【答案提交】
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一
个由大写字母组成的字符串,在提交答案时只填写这个字符串,填写多余的内
容将无法得分。
题解:
#include<iostream>
#include<string>
#include<cstdio>
using namespace std;
string str;
int a[103];
int main(){
str="WHERETHEREISAWILLTHEREISAWAY";
for(int i=0;i<str.size();i++){
a[str[i]]++;
}
for(int i='A';i<='Z';i++){
for(int j=1;j<=a[i];j++) printf("%c",i);
}
return 0;
}
// AAAEEEEEEHHHIIILLRRRSSTTWWWY
试题 B: 特殊时间
本题总分:
5
分
【问题描述】
2022
年
2
月
22
日
22:20
是一个很有意义的时间,年份为
2022
,由
3
个
2
和
1
个
0
组成,如果将月和日写成
4
位,为
0222
,也是由
3
个
2
和
1
个
0
组
成,如果将时间中的时和分写成
4
位,还是由
3
个
2
和
1
个
0
组成。
小蓝对这样的时间很感兴趣,他还找到了其它类似的例子,比如
111
年
10
月
11
日
01:11
,
2202
年
2
月
22
日
22:02
等等。
请问,总共有多少个时间是这种年份写成
4
位、月日写成
4
位、时间写成
4
位后由
3
个一种数字和
1
个另一种数字组成。注意
1111
年
11
月
11
日
11:11
不算,因为它里面没有两种数字。
【答案提交】
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一
个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
题解:
#include<iostream>
#include<string>
#include<cstdio>
using namespace std;
int a[5][3];
int ans;
void solve(int x,int y){
a[1][1]=y*10+x,a[1][2]=x*10+x;
a[2][1]=x*10+y,a[2][2]=x*10+x;
a[3][1]=x*10+x,a[3][2]=y*10+x;
a[4][1]=x*10+x,a[4][2]=x*10+y;
for(int i=1;i<=4;i++){
if(!(a[i][1]>0&&a[i][1]<=12&&a[i][2]>0&&a[i][2]<=30)) continue ;
for(int j=1;j<=4;j++){
if(!(a[j][1]<=24&&a[j][2]<=60)) continue ;
ans++;
// printf("%02d%02d %02d:%02d\n",a[i][1],a[i][2],a[j][1],a[j][2]);
}
}
}
int main(){
for(int i=1;i<=9;i++){
solve(0, i);
solve(i,0);
}
for(int i=2;i<=9;i++){
solve(1, i);
solve(i, 1);
}
cout<<ans*4;
return 0;
}
// 212
试题 C: 纸张尺寸
时间限制
: 1.0s
内存限制
: 256.0MB
本题总分:
10
分
【问题描述】
在
ISO
国际标准中定义了
A0
纸张的大小为
1189
mm
×
841
mm
,将
A0
纸
沿长边对折后为
A1
纸,大小为
841
mm
×
594
mm
,在对折的过程中长度直接取
下整(实际裁剪时可能有损耗)。将
A1
纸沿长边对折后为
A2
纸,依此类推。
输入纸张的名称,请输出纸张的大小。
【输入格式】
输入一行包含一个字符串表示纸张的名称,该名称一定是
A0
、
A1
、
A2
、
A3
、
A4
、
A5
、
A6
、
A7
、
A8
、
A9
之一。
【输出格式】
输出两行,每行包含一个整数,依次表示长边和短边的长度。
【样例输入
1
】
A0
【样例输出
1
】
1189
841
【样例输入
2
】
A1
【样例输出
2
】
841
594
题解:
#include<iostream>
using namespace std;
char ch;
int mxl=1189,mnl=841,t;
int main(){
cin>>ch>>ch;
for(int i=1;i<=ch-'0';i++){
t=mxl/2;
mxl=max(t, mnl);
mnl=min(t, mnl);
}
cout<<mxl<<endl<<mnl;
return 0;
}
试题 D: 求和
时间限制
: 1.0s
内存限制
: 256.0MB
本题总分:
10
分
【问题描述】
给定
n
个整数
a
1
,
a
2
,
· · ·
,
a
n
,求它们两两相乘再相加的和,即
S
=
a
1
·
a
2
+
a
1
·
a
3
+
· · ·
+
a
1
·
a
n
+
a
2
·
a
3
+
· · ·
+
a
n
−
2
·
a
n
−
1
+
a
n
−
2
·
a
n
+
a
n
−
1
·
a
n
.
【输入格式】
输入的第一行包含一个整数
n
。
第二行包含
n
个整数
a
1
,
a
2
,
· · ·
a
n
。
【输出格式】
输出一个整数
S
,表示所求的和。请使用合适的数据类型进行运算。
【样例输入】
4
1 3 6 9
【样例输出】
117
【评测用例规模与约定】
对于
30
%
的数据,
1
≤
n
≤
1000
,
1
≤
a
i
≤
100
。
对于所有评测用例,
1
≤
n
≤
200000
,
1
≤
a
i
≤
1000
。
题解:
分析:先求前缀和,再让每个前缀和 和 数组元素相乘。
#include<iostream>
using namespace std;
long long n,sum,s[200003],a[200003];
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
s[i]=s[i-1]+a[i];
}
for(int i=2;i<=n;i++){
sum+=s[i-1]*a[i];
}
cout<<sum;
return 0;
}
试题 E: 数位排序
时间限制
: 1.0s
内存限制
: 256.0MB
本题总分:
15
分
【问题描述】
小蓝对一个数的数位之和很感兴趣,今天他要按照数位之和给数排序。当
两个数各个数位之和不同时,将数位和较小的排在前面,当数位之和相等时,
将数值小的排在前面。
例如,
2022
排在
409
前面,因为
2022
的数位之和是
6
,小于
409
的数位
之和
13
。
又如,
6
排在
2022
前面,因为它们的数位之和相同,而
6
小于
2022
。
给定正整数
n
,
m
,请问对
1
到
n
采用这种方法排序时,排在第
m
个的元
素是多少?
【输入格式】
输入第一行包含一个正整数
n
。
第二行包含一个正整数
m
。
【输出格式】
输出一行包含一个整数,表示答案。
【样例输入】
13
5
【样例输出】
3
【样例说明】
1
到
13
的排序为:
1, 10, 2, 11, 3, 12, 4, 13, 5, 6, 7, 8, 9
。第
5
个数为
3
。
【评测用例规模与约定】
对于
30
%
的评测用例,
1
≤
m
≤
n
≤
300
。
对于
50
%
的评测用例,
1
≤
m
≤
n
≤
1000
。
对于所有评测用例,
1
≤
m
≤
n
≤
10^
6
。
题解:
#include<iostream>
#include<algorithm>
using namespace std;
struct Node{
int s,data;
}a[1000003];
int n,m;
bool cmp(Node x, Node y){
if(x.s==y.s) return x.data<y.data;
return x.s<y.s;
}
int gets(int x){
int s=0;
while(x){
s+=x%10;
x/=10;
}
return s;
}
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
a[i].data=i;
a[i].s=gets(i);
}
sort(a+1,a+n+1,cmp);
cout<<a[m].data;
return 0;
}
试题 F: 选数异或
时间限制
: 1.0s
内存限制
: 256.0MB
本题总分:
15
分
【问题描述】
给定一个长度为
n
的数列
A
1
,
A
2
,
· · ·
,
A
n
和一个非负整数
x
,给定
m
次查
询
,
每次询问能否从某个区间
[
l
,
r
]
中选择两个数使得他们的异或等于
x
。
【输入格式】
输入的第一行包含三个整数
n
,
m
,
x
。
第二行包含
n
个整数
A
1
,
A
2
,
· · ·
,
A
n
。
接下来
m
行,每行包含两个整数
l
i
,
r
i
表示询问区间
[
l
i
,
r
i
]
。
【输出格式】
对于每个询问
,
如果该区间内存在两个数的异或为
x
则输出
yes
,
否则输出
no
。
【样例输入】
4 4 1
1 2 3 4
1 4
1 2
2 3
3 3
【样例输出】
yes
no
yes
no
【样例说明】
显然整个数列中只有
2
,
3
的异或为
1
。
【评测用例规模与约定】
对于
20
%
的评测用例,
1
≤
n
,
m
≤
100
;
对于
40
%
的评测用例,
1
≤
n
,
m
≤
1000
;
对于所有评测用例,
1
≤
n
,
m
≤
100000
,
0
≤
x
<
2^
20
,
1
≤
l
i
≤
r
i
≤
n
,
0
≤
A
i
<
2^
20
。
题解:
分析:这是我暴力做的,过了40%。
#include<iostream>
using namespace std;
int n,m,x,l,r;
int a[100003];
int main(){
cin>>n>>m>>x;
for(int i=1;i<=n;i++) cin>>a[i];
while(m--){
cin>>l>>r;
bool flag=true;
for(int i=l;i<=r;i++){
for(int j=i+1;j<=r;j++){
if((a[i]^a[j])==x){
flag=false;
cout<<"yes"<<endl;
break;
}
}
if(!flag) break;
}
if(flag) cout<<"no"<<endl;
}
return 0;
}
学习了一些别人的博客,然后 AC 了100%。这里用了动态规划来做,然后要明白:
a^b=x => a^x=b 。
#include<iostream>
using namespace std;
int n,m,x,l,r,data;
//mp[i] 用于存取 i 出现的位置
//dp[i] 用于存取 i 之前与当前数异或等于x的位置
int mp[1<<20],dp[100002];
int main(){
cin>>n>>m>>x;
for(int i=1;i<=n;i++){
cin>>data;
dp[i]=max(dp[i-1], mp[data^x]);
mp[data]=i;
}
while(m--){
cin>>l>>r;
if(dp[r]>=l) cout<<"yes"<<endl;
else cout<<"no"<<endl;
}
return 0;
}
试题 G: 消除游戏
时间限制
: 1.0s
内存限制
: 256.0MB
本题总分:
20
分
【问题描述】
在一个字符串
S
中,如果
S
i
=
S
i
−
1
且
S
i
,
S
i
+1
,则称
S
i
和
S
i
+1
为边缘
字符。如果
S
i
,
S
i
−
1
且
S
i
=
S
i
+1
,则
S
i
−
1
和
S
i
也称为边缘字符。其它的字符
都不是边缘字符。
对于一个给定的串
S
,一次操作可以一次性删除该串中的所有边缘字符
(操作后可能产生新的边缘字符)。
请问经过
2
64
次操作后,字符串
S
变成了怎样的字符串,如果结果为空则
输出
EMPTY
。
【输入格式】
输入一行包含一个字符串
S
。
【输出格式】
输出一行包含一个字符串表示答案,如果结果为空则输出
EMPTY
。
【样例输入
1
】
edda
【样例输出
1
】
EMPTY
【样例输入
2
】
sdfhhhhcvhhxcxnnnnshh
【样例输出
2
】
s
【评测用例规模与约定】
对于
25
%
的评测用例,
|
S
| ≤
10
3
,其中
|
S
|
表示
S
的长度;
对于
50
%
的评测用例,
|
S
| ≤
10
4
;
对于
75
%
的评测用例,
|
S
| ≤
10
5
;
对于所有评测用例,
|
S
| ≤
10
6
,
S
中仅含小写字母。
题解:
试题 H: 重新排序
时间限制
: 1.0s
内存限制
: 256.0MB
本题总分:
20
分
【问题描述】
给定一个数组
A
和一些查询
L
i
,
R
i
,求数组中第
L
i
至第
R
i
个元素之和。
小蓝觉得这个问题很无聊,于是他想重新排列一下数组,使得最终每个查
询结果的和尽可能地大。小蓝想知道相比原数组,所有查询结果的总和最多可
以增加多少
?
【输入格式】
输入第一行包含一个整数
n
。
第二行包含
n
个整数
A
1
,
A
2
,
· · ·
,
A
n
,相邻两个整数之间用一个空格分隔。
第三行包含一个整数
m
表示查询的数目。
接下来
m
行,每行包含两个整数
L
i
、
R
i
,相邻两个整数之间用一个空格分
隔。
【输出格式】
输出一行包含一个整数表示答案。
【样例输入】
5
1 2 3 4 5
2
1 3
2 5
【样例输出】
4
【样例说明】
原来的和为
6 + 14 = 20
,重新排列为
(1
,
4
,
5
,
2
,
3)
后和为
10 + 14 = 24
,增
加了
4
。
【评测用例规模与约定】
对于
30
%
的评测用例,
n
,
m
≤
50
;
对于
50
%
的评测用例,
n
,
m
≤
500
;
对于
70
%
的评测用例,
n
,
m
≤
5000
;
对于所有评测用例,
1
≤
n
,
m
≤
10^
5
,
1
≤
A
i
≤
10^
6
,
1
≤
L
i
≤
R
i
≤
10^
6
。
题解:
分析:这里由于数据有点大,暴力不能全部过,所以用了差分。(注意:int数据类型 * int数据类型赋值给 long long 类型,不能自动转换为long long,所以我就干脆全部设为long long 类型了)
#include<iostream>
#include<algorithm>
using namespace std;
const int N=100003;
long long n,num[N];
long long m,l,r,b[N],a[N];
long long s1,s2;
int main(){
cin>>n;
for(int i=1;i<=n;i++) cin>>num[i];
cin>>m;
while(m--){
cin>>l>>r;
b[l]+=1;
b[r+1]-=1;
}
// a数组存放的是当前位置查询的次数
for(int i=1;i<=n;i++){
a[i]=a[i-1]+b[i];
s1+=a[i]*num[i];
}
sort(num+1, num+n+1);
sort(a+1, a+n+1);
for(int i=1;i<=n;i++){
s2+=a[i]*num[i];
}
cout<<s2-s1;
return 0;
}
试题 I: 技能升级
时间限制
: 1.0s
内存限制
: 256.0MB
本题总分:
25
分
【问题描述】
小蓝最近正在玩一款
RPG
游戏。他的角色一共有
N
个可以加攻击力的技
能。其中第
i
个技能首次升级可以提升
A
i
点攻击力,以后每次升级增加的点数
都会减少
B
i
。
⌈
A
i/
B
i
⌉
(
上取整
)
次之后,再升级该技能将不会改变攻击力。
现在小蓝可以总计升级
M
次技能,他可以任意选择升级的技能和次数。请
你计算小蓝最多可以提高多少点攻击力?
【输入格式】
输入第一行包含两个整数
N
和
M
。
以下
N
行每行包含两个整数
A
i
和
B
i
。
【输出格式】
输出一行包含一个整数表示答案。
【样例输入】
3 6
10 5
9 2
8 1
【样例输出】
47
【评测用例规模与约定】
对于
40
%
的评测用例,
1
≤
N
,
M
≤
1000
;
试题
I:
技能升级
14
第十三届蓝桥杯大赛软件赛省赛
C/C++
大学
C
组
对于
60
%
的评测用例,
1
≤
N
≤
10^
4
,
1
≤
M
≤
10^
7
;
对于所有评测用例,
1
≤
N
≤
10^
5
,
1
≤
M
≤
2
×
10^
9
,
1
≤
A
i
,
B
i
≤
10^
6
。
题解:
分析:我是通过暴力进行求解,AC了 40%,然后用二分进行了下优化,AC了 60%。
#include<iostream>
#include<algorithm>
using namespace std;
long long n,m;
long long s;
struct Node{
int a,b;
}node[100003];
bool cmp(Node x,Node y){
return x.a<y.a;
}
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>node[i].a>>node[i].b;
}
sort(node+1, node+n+1, cmp);
while(m--){
if(node[n].a<=0) break;
s+=node[n].a;
node[n].a-=node[n].b;
int l=1,r=n-1,ta=node[n].a,tb=node[n].b;
while(l<r){
int mid=(l+r)>>1;
if(node[mid].a<ta) l=mid+1;
else r=mid;
}
if(l==n-1&&node[n-1].a<ta) continue ;
for(int i=n-1;i>=l;i--){
node[i+1].a=node[i].a;
node[i+1].b=node[i].b;
}
}
cout<<s;
return 0;
}
试题 J: 重复的数
时间限制
: 1.0s
内存限制
: 256.0MB
本题总分:
25
分
【问题描述】
给定一个数列
A
= (
a
1
,
a
2
,
· · ·
,
a
n
)
,给出若干询问,每次询问某个区间
[
l
i
,
r
i
]
内恰好出现
k
i
次的数有多少个。
【输入格式】
输入第一行包含一个整数
n
表示数列长度。
第二行包含
n
个整数
a
1
,
a
2
,
· · ·
,
a
n
,表示数列中的数。
第三行包含一个整数
m
表示询问次数。
接下来
m
行描述询问,其中第
i
行包含三个整数
l
i
,
r
i
,
k
i
表示询问
[
l
i
,
r
i
]
区
间内有多少数出现了
k
i
次。
【输出格式】
输出
m
行,分别对应每个询问的答案。
【样例输入】
3
1 2 2
5
1 1 1
1 1 2
1 2 1
1 2 2
1 3 2
【样例输出】
1
0
2
0
1
【评测用例规模与约定】
对于
20
%
的评测用例,
n
,
m
≤
500
,
1
≤
a
1
,
a
2
,
· · ·
,
a
n
≤
1000
;
对于
40
%
的评测用例,
n
,
m
≤
5000
;
对于所有评测用例,
1
≤
n
,
m
≤
100000
,
1
≤
a
1
,
a
2
,
· · ·
,
a
n
≤
100000
,
1
≤
l
i
≤
r
i
≤
n
,
1
≤
k
i
≤
n
。
题解:
分析:暴力求解,AC了 20%。
#include<iostream>
#include<cstring>
using namespace std;
const int N=100002;
int n,m,a[N],l,r,k;
int num[N];
int main(){
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
cin>>m;
while(m--){
cin>>l>>r>>k;
memset(num, 0, sizeof(num));
int cnt=0;
// 此处会超时
for(int i=l;i<=r;i++){
num[a[i]]++;
if(num[a[i]]==k) cnt++;
else if(num[a[i]]==k+1) cnt--;
}
cout<<cnt<<endl;
}
return 0;
}