U
P
D
:
2022.11.10
UPD:2022.11.10
UPD:2022.11.10程设课的
x
d
m
xdm
xdm别抄代码了,都被查重了,写博客是让你们更好理解题,不是给你们答案让你们搜的
如图
谁能想到一个月前发的博客无意间成了钓鱼贴捏
问题 A: 红警之王MFC
题目描述
红警是一款经典的即时战略游戏,MFC爱玩红警到了痴迷的程度!
一天晚上,MFC打红警到凌晨2点,恍惚之间他发现自己进入了红警的世界,他现在的身份是一个一星动员兵!
在一场遭遇战中,他来到了“冷酷的敌人”的基地,对于他来说,他面前有N个建筑,每个建筑有四种属性,分别是 类型、生命值、x坐标、y坐标。
动员兵MFC被玩家指定了攻击顺序,他必须按照读入的顺序依次推倒每个建筑,具体来说:
MFC初始位于坐标(0,0)处,初始攻击力为30,首先它将以1单位每秒的速度移动到建筑的位置,之后他将每秒对建筑造成等同于他当前攻击力的伤害,当建筑物生命值降到0时,建筑物被摧毁,MFC将前去摧毁下一个建筑,直到所有建筑被摧毁,MFC将获得胜利。
值得注意的是,当MFC摧毁3座建筑后,他会升至二星并拥有40攻击力。当他再摧毁5座建筑后,他会升至三星并拥有55攻击力。星级提升不会影响他的移动速度,坐标间距离的计算方式采用欧几里得距离,即两点之间的最短线段长度,移动带来的时间消耗向下取整。
MFC想知道,他将在多少秒后完成任务。
输入
第一行一个整数 N
接下来N行每行四个量 name hp x y,分别表示第i个建筑的种类、生命值、x坐标、y坐标。
输出
一行,包含一个整数,代表MFC完成任务的时间。
样例输入 1 1 1
4
Barracks 446 48 9
PowerPlant 322 17 7
OreRefinery 414 6 36
ConstructionYard 316 12 20
样例输出 1 1 1
175
提示
本题背景经过真实事件改编,建筑物种类均采用官方英文名!
S
o
l
u
t
i
o
n
:
Solution:
Solution:
模拟 对每次输入的建筑物进行操作
先判断摧毁建筑物的次数以确定攻击力
再计算移动时间和摧毁时间
最后储存当前位置 便于下次判断
上代码↓
#include<bits/stdc++.h>
using namespace std;
inline void read(long long &x){
long long s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){s=(s<<3)+(s<<1)+(ch&15);ch=getchar();}
x=s*w;
}
string nam;
long long n,now=30,tim,hp,x,y,nowx,nowy;
int main(){
read(n);
for(int i=1;i<=n;i++){
cin>>nam;
read(hp),read(x),read(y);
tim+=(long long)(sqrt((nowx-x)*(nowx-x)+(nowy-y)*(nowy-y)));
nowx=x,nowy=y;
if(i>3)now=40;
if(i>8)now=55;
tim+=hp/now+(hp%now>0);
}
cout<<tim<<endl;
}
问题 B: NUMBERS
题目描述
H
Z
L
h
a
s
n
n
u
m
b
e
r
s
a
0
,
a
1
,
…
,
a
n
d
M
F
C
h
a
s
m
n
u
m
b
e
r
s
b
0
,
b
1
,
…
,
b
m
−
1
HZL\,\, has\,\, n\,\, numbers\,\, a_0, a_1, \dots , and \,\,MFC \,\,has\,\, m\,\, numbers\,\, b_0, b_1, \dots, b_{m-1}
HZLhasnnumbersa0,a1,…,andMFChasmnumbersb0,b1,…,bm−1
M
F
C
w
o
n
d
e
r
s
f
o
r
e
a
c
h
b
i
,
h
o
w
m
a
n
y
a
j
a
r
e
s
t
r
i
c
t
l
y
l
e
s
s
t
h
a
n
b
i
MFC\,\, wonders\,\, for\,\, each \,\,b_i\,\, , how \,\,many\,\, a_j \,\, are \,\,strictly\,\, less\,\, than\,\, b_i
MFCwondersforeachbi,howmanyajarestrictlylessthanbi
输入
The first line contains two integer nn and mm.
The second line contains nn numbers separated by spaces, representing
a
0
,
a
1
,
…
,
a
n
−
1
a_0, a_1, \dots , a_{n - 1}
a0,a1,…,an−1 .
The third line contains mm numbers separated by spaces, representing
b
0
,
b
1
,
…
b
m
−
1
b_0, b_1, \dots b_{m-1}
b0,b1,…bm−1 .
输出
Output one line with mm integer separated by spaces.
The
i
t
h
i^{th}
ith integer represents the number of
a
j
a_j
aj that are strictly less than
b
i
b_i
bi
.
样例输入 1 1 1
5 7
3 -2 5 -1 4
6 -5 -4 3 2 -1 0
样例输出 1 1 1
5 0 0 2 2 1 2
样例输入 2 2 2
6 7
1 1 4 5 1 4
1 9 1 9 8 1 0
样例输出 2 2 2
0 6 0 6 6 0 0
提示
1
≤
n
,
m
≤
200
,
000
1≤n,m≤200,000
1≤n,m≤200,000
All numbers are 32-bit signed integer.
题意:给你两个数组
a
、
b
a、b
a、b 问你对于
b
b
b数组的每个数
a
a
a数组里有多少个数严格比它小
S
o
l
u
t
i
o
n
:
Solution:
Solution:
数据范围
n
,
m
n,m
n,m都是
2
e
6
,
2e6,
2e6,显然不能
n
2
n^2
n2暴力做
先将
a
a
a数组排序 再对于每个
b
b
b数组的数再
a
a
a数组中进行二分查找
时间复杂度
O
(
n
l
o
g
n
)
O(nlog_n)
O(nlogn)
上代码↓
#include<bits/stdc++.h>
#define N 200020
#define reg register
using namespace std;
inline void read(int &x){
int s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){s=(s<<3)+(s<<1)+(ch&15);ch=getchar();}
x=s*w;
}
int n,m,a[N],b[N];
int main(){
read(n),read(m);
for(reg int i=1;i<=n;i++)read(a[i]);
for(reg int i=1;i<=m;i++)read(b[i]);
sort(a+1,a+1+n);
cout<<lower_bound(a+1,a+1+n,b[1])-a-1;
for(reg int i=2;i<=m;i++){
printf(" %d",lower_bound(a+1,a+1+n,b[i])-a-1);
}
puts("");
}
问题 C: 小D的方格取数
题目描述
小D有个nxm的正整数矩阵,他让小M找到这样的一个子矩阵
子矩阵的价值定义为,矩阵所有元素的和 / 矩阵最后一行元素的和。
现在小D想知道,对于初始的矩阵,价值最大的子矩阵价值是多少呢?
输入
- 第一行一个整数T,表示数据组数
- 之后T组数据,第一行两个正数n,m代表矩阵的尺寸
- 之后n行每行m个整数,代表小D给出的矩阵。
输出
输出共T行,每行一个小数,代表第T次询问的答案。
样例输入 1 1 1
1
3 3
1 3 5
6 8 9
2 7 4
样例输出 1 1 1
4.50000000
提示
- t<=100
- n,m<=200
- a i j < = 5 × 1 0 4 a_{ij} <=5 \times 10^4 aij<=5×104
- 1e-5的误差
S
o
l
u
t
i
o
n
:
Solution:
Solution:
显然题目所求价值最大子矩阵一定是一列的
证明:
设第
i
i
i列第
m
m
m行元素为
a
m
,
i
a{m,i}
am,i,第
i
i
i列所有元素的和为
s
i
s_i
si
则
∑
s
i
∑
a
i
≤
m
a
x
{
s
i
a
i
}
\frac{\sum s_i}{\sum a_i} \le max\{\frac{s_i}{a_i}\}
∑ai∑si≤max{aisi}
因此价值最大子矩阵一定出自某一列
只需对每一列判断即可
上代码↓
#include<bits/stdc++.h>
#define reg register
using namespace std;
inline void read(int &x){
int s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){s=(s<<3)+(s<<1)+(ch&15);ch=getchar();}
x=s*w;
}
int t,n,m,sqr[220][220],sum[220][220];
double ans;
int main(){
read(t);
while(t--){
memset(sum,0,sizeof sum);ans=0.0;
read(n),read(m);
for(reg int i=1;i<=n;i++){
for(reg int j=1;j<=m;j++)read(sqr[i][j]),sum[i][j]=sqr[i][j]+sum[i-1][j];
}
for(reg int j=1;j<=m;j++){
for(reg int i=n;i;i--){
ans=max(ans,sum[i][j]*1.000000000/sqr[i][j]);
}
}
printf("%.6lf\n",ans);
}
}
问题 D: zzj数
题目描述
什么叫做zzj数呢❓
zzj数是什么呢❓
小编也很惊讶zzj数是什么❓
小编相信大家都很熟悉,但小编也感到非常惊讶zzj数是什么,下面就让小编带大家了解一下zzj数。
对于一个数字n,我们必须采取一次操作: 交换其相邻的两位。
经过交换后得到的最大的数为zzj数。
聪明的你看到这里一定知道你要做什么了:,
输入
给定一个数字n。
数据范围: 10 <= n <= 1e8
输出
输出其zzj数。
样例输入 1 1 1
19260817
样例输出 1 1 1
91260817
题意:这题面纯纯
n
t
nt
nt 题意就是给你一个两位及以上的数 必须将相邻的两位交换 求交换之后的最大数
S
o
l
u
t
i
o
n
:
Solution:
Solution:
从最高位开始判断 如果交换之后变大就直接交换
如果交换之后都不能变大 就先看看有没有相邻两位一样的 交换之后数大小不变
实在不行就交换最后两位
注意判断
10
10
10这种交换之后
0
0
0在首位的
上代码↓
#include<bits/stdc++.h>
using namespace std;
char s[10];
int main(){
scanf("%s",s);
int len=strlen(s),pd=0,tn=0;
for(int i=1;i<len;i++){
if(s[i]>s[i-1]){
char tmp=s[i];
s[i]=s[i-1],s[i-1]=tmp,tn=1;
break;
}
else if(s[i]==s[i-1])pd=1;
}
if(pd)puts(s);
else if(tn)puts(s);
else{
char tmp=s[len-1];
s[len-1]=s[len-2],s[len-2]=tmp;
int k=0;
for(int i=0;i<len;i++){
if(s[i]!='0')k=1;
if(k)putchar(s[i]);
}
puts("");
}
}
问题 E: 魔法阵
题目描述
有一个圆形的魔法阵,圆形法阵的圆周上有N个点。当法阵圆周上的某四个不同的点恰好能组成矩形时,法阵的能产生1单位的能量。(注:若至少存在一个节点不相同,则认为两个矩形不相同,同一个点可以被统计到多个矩形中)
现在,已知相邻两点间的弧长均为正整数,按照以某一点为起点顺序给出相邻两点间弧长,求这个法阵能产生多少单位的能量。
输入
第一行一个整数N
接下来N行,每行一个整数,分别代表相邻两点间分割的圆弧长度。
输出
一个整数,代表法阵产生的能量。
样例输入 1 1 1
8
1
2
2
3
1
1
3
3
样例输出 1 1 1
3
提示
对于40%的数据,满足N<=20
对于70%的数据,满足N<=5000
对于100%的数据,满足N<=200000
S
o
l
u
t
i
o
n
:
Solution:
Solution:
在圆周上的四个点能围出一个矩形的前提条件是有两对关于圆心对称的点
因此我们找出关于圆心对称的点 即两点间圆弧距离等于半径的一对点
先将第一个点坐标设为
0
0
0 按圆弧为坐标轴 依次将每个点标上坐标
对于每个点 利用二分查找点坐标数组中与他圆弧距离等于半径的点
假设找到了
k
k
k对
那么答案就是
C
k
2
C_k^2
Ck2
记得开
l
o
n
g
l
o
n
g
long\,\,long
longlong
上代码↓
#include<bits/stdc++.h>
#define N 200020
using namespace std;
inline void read(long long &x){
long long s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){s=(s<<3)+(s<<1)+(ch&15);ch=getchar();}
x=s*w;
}
long long n,sum,r,edge[N],pnt[N];
int main(){
read(n);
for(long long i=1;i<=n;i++)read(edge[i]),r+=edge[i];
for(long long i=1;i<=n;i++)pnt[i]=pnt[i-1]+edge[i];
if(r&1){puts("0");return 0;}
for(long long i=0;i<n;i++){
if(pnt[lower_bound(pnt,pnt+n,(pnt[i]+r/2)%r)-pnt]==(pnt[i]+r/2))sum++;
}
cout<<sum*(sum-1)/2<<endl;
}