A石头剪刀布
题目
内存限制: 256 MB
时间限制: 1000 ms
题目描述
小T和小K在同一个小组,平时两人非常友爱,可每当轮到他们小组值日时,两人经常会为了扫地擦黑板之类的小事争执。一旦争执起来,他们就通过古老的猜拳游戏石头、剪刀、布来决定胜负(游戏规则:石头打剪刀,布包石头,剪刀剪布。),胜的一方获得优先选择权,如小T胜了他总是选择擦黑板,因为他长得人高马大,擦起黑板来挥洒自如,相对而言扫地就费劲多了,由于扫帚很短,他要把腰弯得很低才能扫到地面。
令小T烦恼的是他总是输多胜少,原因是小K常常在最后时刻变换手势,明明开始时是石头,可到了小T面前又变成了剪刀。
小T想了很久也没能想出什么好办法,直到有一天小T去某蒙看了电影《非诚勿扰》,影片中介绍了科学家秦奋发明“分歧终端机”的事迹,小T看完后深受启发,一回家就立刻着手制作起自己的“分歧终端机”来。
小T的“分歧终端机”形状是一个全封闭的长方体盒子,盒子的上表面装有一个电子显示屏,用来显示结果,左右两侧各有一个键盘,键盘上有3个键,上面标有数字1、2、3,分别代表石头、剪刀、布,如果选手要出石头则按1号键,要出剪刀则按2号键,要出布则按3号键。猜拳开始两位选手随即根据自己的意愿去按相应的键,如果第一次两人按的键相同,则不分胜负,继续第二次按键,直到决出胜负为止。
他希望你来帮他完成这个任务,这个任务非常简单,你可不能让小T失望哦~。
输入格式
仅有一行包含两个用空格隔开的不超过3的自然数,表示小T和小K所按键上的数字,1表示石头,2表示剪刀,3表示布。游戏规则是石头胜剪刀,剪刀胜布,布胜石头。
输出格式
仅有一行输出本次猜拳的结果,如果小T胜则输出“win”,如果小T输则输出“lose”,如果两人不分胜负则输出“tie”。注意输出时都用小写字母,引号不要输出。
样例
输入 #1
1 2
输出 #1
win
分析
令人费解的题干长度。
没什么好说的,纯模拟(本蒟蒻懒得推通解,直接暴力判断了)。
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
int a,b;
int main()
{
cin>>a>>b;
if(a==b)cout<<"tie";
else if(a==1){
if((b==2))cout<<"win";
else cout<<"lose";
}
else if(a==2){
if((b==3))cout<<"win";
else cout<<"lose";
}
else if(a==3){
if((b==1))cout<<"win";
else cout<<"lose";
}
return 0;
}
B保家卫国
题目
内存限制: 256 MB
时间限制: 1000 ms
题目描述
最近,有一个比较火的电视剧《特战荣耀》,如果大家看完以后,是否有当兵的想法呢?
这天下午,你正在看《特战荣耀》,突然,楼下有人在喊,说是部队来家乡招兵了,正合你意,你高兴的跑过去一看,发现招兵是有条件的(身高必须在160cm+),并且给补贴(补贴的很高,是以个人身高为基础,进行补贴)。
(1) 如果是男性,那么:
如果身高在170cm以下(包含170cm),将享受国家85%的补贴。
如果身高在170cm以上,180cm以下(含180cm)将享受国家80%的补贴。
如果身高在180cm以上,可以享受国家75%的补贴,还将获得一个惊喜大礼包。
(2) 如果是女性,那么:
如果身高在170cm以下(包含170cm),将享受国家90%的补贴。
如果身高在170cm以上,可以享受国家90%的补贴,还将获得一个惊喜大礼包。
请你根据性别和身高,计算一下可以享受国家多少补贴,以及是否可以领取大礼包。
输入格式
第一行一个字符’Y’或’C’ ,'Y’表示男性,'C’表示是女性。
第二行一个正整数,int范围内, 表示身高。
输出格式
第一行表示是否可以领取大礼包,如果可以输出’YES’,否则输出’NO’。
第二行一个实数,保留两位小数,表示享受的补贴。
样例
输入
Y
189
输出
NO
144.00
分析
同A题。
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
char a;
int b;
int main()
{
cin>>a>>b;
//if(b<160){
// cout<<"NO\n0";
// return 0;
//}并没有关于这个特判的测试点,可有可无
if(a=='V'){
if(b<=170)
printf("NO\n%.2lf",b*0.85);
else if(b<=180)
printf("NO\n%.2lf",b*0.8);
else printf("YES\n%.2lf",b*0.75);
}
else {
if(b<=170)
printf("NO\n%.2lf",b*0.9);
else printf("YES\n%.2lf",b*0.9);
}
return 0;
}
C 数字游戏
题目
内存限制: 256 MiB
时间限制: 1000 ms
题目描述
你的朋友在玩数字游戏,游戏规则如下:
起始数字为
x
x
x ,每一轮如果
x
x
x的最大质因子大于
p
p
p时,
x
x
x增加1点。
请你计算出经过尽可能多轮游戏后,最终的
x
x
x值。
输入格式
两个整数 x x x, p p p。
输出格式
一个整数,表示你最终的 x x x值。
样例
【样例1输入】
666 2
【样例1输出】
1024
【样例2输入】
114514 3
【样例2输出】
118098
【样例3输入】
1919810 9
【样例3输出】
1920000
【样例4输入】
314159265 2
【样例4输出】
536870912
数据范围与提示
对于10% 的数据,保证
p
=
2
p = 2
p=2。
对于30% 的数据,保证
x
≤
20
x ≤ 20
x≤20。
对于另外10% 的数据,保证
p
=
2
p = 2
p=2。
对于70% 的数据,保证
x
≤
1
0
6
x ≤ 10^{6}
x≤106。
对于另外10% 的数据,保证
p
=
2
p = 2
p=2。
对于100% 的数据,满足
2
≤
x
≤
6
×
1
0
8
2 ≤ x ≤ 6×10^{8}
2≤x≤6×108,
2
≤
p
≤
10
2 ≤ p ≤ 10
2≤p≤10。
分析
本场比赛第一道非红题。话说csp-j模拟赛怎么越来越水了。
通过题意,我们发现最终的 x x x 值即为不小于初始 x x x 值得最小的最大质因子不大于 p p p 的数,即其质因数都为小于 p p p 的质数。
但是 x x x 的值太大,暴力枚举显然会 T L E TLE TLE。因为数据范围中的 1 ≤ p ≤ 10 1\le p\le 10 1≤p≤10 非常小,所以从此入手。 10 10 10 以内的质数只有 2 , 3 , 5 , 7 2,3,5,7 2,3,5,7,我们可以定义一个优先队列 q q q(小顶堆),初始队列为所有不大于 p p p 的素数。然后每次弹出队头,即目前最小的满足条件的数,判断其是否不小于 x x x,不小于则输出,否则枚举小于 p p p 的素数,然后将两数相乘后放入 q q q。根据素数唯一分解定理,生成的数不会重复。
关于时间复杂度…反正能过(我不会证)。
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
int x,p;
priority_queue<ll,vector<int>,greater<int> >q;
int a[6]={0,2,3,5,7,11};//多写一个作为边界
int main()
{
cin>>x>>p;
ll ans;
for(int i=1;a[i]<=p;i++)
q.push(a[i]);
while(1){
int t=q.top();q.pop();
if(t>=x){
ans=t;
break;
}
for(int i=1;a[i]<=p;i++)
q.push(t*a[i]);
}
cout<<ans;
return 0;
}
D 魔力碎片
题目
内存限制: 256 MiB
时间限制: 1000 ms
题目描述
你的手中共有
x
x
x点「魔力碎片」。
每次,你可以消耗
k
k
k点「魔力碎片」进行「融合」,得到1点「魔力」并返还
p
p
p点「魔力碎片」。
请你求出你可以获得的「魔力」的最大值。
输入格式
三个整数 x x x, k k k, p p p。
输出格式
仅一个数,表示你可以获得的「魔力」的最大值。
样例
【样例1输入】
6 3 2
【样例1输出】
4
【样例2输入】
114514 666 233
【样例2输出】
263
【样例3输入】
1000000000000666 50000001919810 5000000114514
【样例3输出】
62088969
数据范围与提示
对于10% 的数据,保证
p
=
0
p = 0
p=0。
对于50% 的数据,
0
≤
x
,
p
≤
1
0
3
0 ≤ x,p ≤ 10^{3}
0≤x,p≤103,
p
≤
k
≤
1
0
3
p ≤ k ≤ 10^{3}
p≤k≤103。
对于另外20% 的数据,保证
x
<
k
x < k
x<k。
对于100% 的数据,
0
≤
x
,
p
≤
1
0
18
0 ≤ x,p ≤ 10^{18}
0≤x,p≤1018,
p
≤
k
≤
1
0
18
p ≤ k ≤ 10^{18}
p≤k≤1018。
题目保证答案不大于
1
0
18
10^{18}
1018。
分析
每次操作都会使 x x x 的值减去 k − p k-p k−p,所以只要求出 ⌊ x k − p ⌋ ⌊\frac{x}{k-p}⌋ ⌊k−px⌋ 即可…
显然,这是错误的。当进行到某次操作使 k − p < x < k k-p<x<k k−p<x<k 时,上面的式子会错误的多计算 ⌊ x k − p ⌋ ⌊\frac{x}{k-p}⌋ ⌊k−px⌋ 点(这里的 x x x 为某次操作后得值而非初始值)。
所以,我们可以将计算分为两部分。先计算出当剩余值大于 x − k x-k x−k 时对答案的贡献,推得贡献为 ⌊ x − k k − p ⌋ ⌊\frac{x-k}{k-p}⌋ ⌊k−px−k⌋。然后, x x x 的值就只剩下 k k k 点,正好可以再进行一次操作,贡献为 1 1 1。两次操作剩余值之和显然不会达到 k k k。
所以,我们可以得到答案为:
⌊
x
−
k
k
−
p
⌋
+
1
⌊\frac{x-k}{k-p}⌋+1
⌊k−px−k⌋+1
此外,还有一个特判要注意。当 x < k x<k x<k 时,无法进行操作,直接输出 0 0 0。
code(疯狂压行版)
#include<bits/stdc++.h>
using namespace std;
long long x,k,p;
int main()
{
cin>>x>>k>>p;
if(x<k)return !(cout<<0);
return !(cout<<(x-k)/(k-p)+1);
}
E Present
题目
内存限制: 256 MiB
时间限制: 1000 ms
题目描述
很多人,都有着奋力挣扎的当下。
车水马龙,人来人往。有很多人渐渐进入你的生活,也有很多人陆续淡出你的视野。
为了方便,用整数来标识每个人。你的思绪可以类比成一根绳索,而每个人就像穿上去的珍珠。每一天,可能有一颗“珍珠”从最左侧或最右侧加入了这条绳索;也有可能会有一颗“珍珠”被你从最左侧或最右侧取下;甚至也有可能发生了些变故,致使你的整个“项链”左右翻转了过来。
每当一个人离开的时候,你总会缅怀一下他,输出标识他的数字来结束这一段关系。
最开始你的思绪中空无一人。在接下来的这
n
n
n天中,你又会先后缅怀哪些人呢?
输入格式
第一行一个整数
n
n
n,
i
d
id
id,表示需要处理的天数和测试点编号(方便您获取部分分,见“数据范围与提示”部分)。
接下来
n
n
n行,每行的格式是以下5种之一:
- 0 x 0\ x 0 x:从最左侧加入标识为 x x x的人( x x x是一个整数)
- 1 1 1:移除并缅怀最左侧的人(要求输出其标识)。若不存在,输出 0 0 0
- 2 x 2\ x 2 x:从最右侧加入标识为 x x x的人( x x x是一个整数)
- 3 3 3:移除并缅怀最右侧的人(要求输出其标识)。若不存在,输出 0 0 0
- 4 4 4:使思绪颠倒(整条“项链”左右翻转)
输出格式
每当操作为 1 1 1或 3 3 3时,输出一行一个整数,表示被移除的人的标识数(若不存在则输出 0 0 0)。
样例
【样例1输入】
8 0
1
2 111
0 222
4
0 333
3
1
3
【样例1输出】
0
222
333
111
第 1 天,试图移除最左侧的人,但此时思绪为空不存在最左侧的人,故输出 0。
第 2,3 天在右侧加入 111,左侧加入 222 后你的思绪可以表示为 “222 111”。
第 4 天翻转变为 “111 222”。
第 5 天左侧加入 333 得到 “333 111 222”。
第 6 天移除并输出最右侧的 222 剩下 “333 111”。
第 7,8 天同理。
数据范围与提示
分析
直接用 S T L STL STL 的双端队列或手写双端队列模拟即可(我用的是 S T L STL STL)。需要注意的是,翻转队列使用一般写法可能会超时,记录一个变量 i o io io 判断当前方向即可。
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,id,io=1;
deque<int> q;
signed main()
{
cin>>n>>id;
while(n--){
int op;cin>>op;
if(op==0){
int x;cin>>x;
if(io==1)
q.push_front(x);
else q.push_back(x);
}
else if(op==1){
if(q.empty())cout<<"0\n";
else
if(io==1){
cout<<q.front()<<"\n";
q.pop_front();
}
else {
cout<<q.back()<<"\n";
q.pop_back();
}
}
else if(op==2){
int x;cin>>x;
if(io==-1)
q.push_front(x);
else q.push_back(x);
}
else if(op==3){
if(q.empty())cout<<"0\n";
else
if(io==-1){
cout<<q.front()<<"\n";
q.pop_front();
}
else {
cout<<q.back()<<"\n";
q.pop_back();
}
}
else if(op==4)
io*=-1;
}
return 0;
}
F 人赢
题目
内存限制: 256 MiB
时间限制: 1000 ms
题目描述
在某个群里,有一个人赢,他很关心群友的未来前途。
在把群友从 1 到
n
n
n编号后,他给每个群友的人生做出了评价,用人生路值来表示,记作
c
i
c_i
ci。
群友的数量
n
n
n恰好是偶数,所以他想出了一个好办法:相对帮扶。
他发现,一对群友的人生路值差距越大,他们之间相互帮扶的效果就越好。具体而言,如果这对群友的人生路值分别是
c
a
c_a
ca和
c
b
c_b
cb,那么就会产生
(
c
a
−
c
b
)
2
(c_a - c_b)^2
(ca−cb)2的效果。
他想知道在合理结对之后,产生的效果之和最大是多少。如果有能力的话,他还想让你具体地给出能产生这么多效果的方案是如何结对的。(每个人必须参与且仅参与一次结对)
输入格式
第一行给出两个整数
n
n
n,
f
l
a
g
flag
flag,表示群友的人数,以及是否需要输出方案。
第二行
n
n
n个正整数
c
i
c_i
ci,表示编号为
i
i
i的群友的人生路值。
输出格式
第一行一个整数,表示可能的最大的效果和。
此后如果
f
l
a
g
flag
flag为 0,不需要输出其它内容。否则你还需要按如下格式输出方案:
共
n
2
\frac{n}{2}
2n行,每行两个整数
x
x
x,
y
y
y表示要让编号为
x
x
x和
y
y
y的群友结成一对,其中要求
c
x
≥
c
y
c_x \geq c_y
cx≥cy。
先输出产生的效果更大的一对,如果有两对产生的效果大小相同,则顺序任意。
若存在多种方案,输出任意一种即可。
样例
【样例1输入】
4 0
22 44 33 11
【样例1输出】
1210
【样例2输入】
4 1
22 44 33 11
【样例2输出】
1210
2 4
3 1
两个样例情况相同,第一个不要求输出方案,第二个要求输出方案。
可以证明 2 和 4 组队、1 和 3 组队能产生的总效果是最大的。由于
(
c
2
−
c
4
)
2
≥
(
c
3
−
c
1
)
2
(c_2 - c_4)^2 \geq (c_3 - c_1)^2
(c2−c4)2≥(c3−c1)2,所以先输出
(
2
,
4
)
(2,4)
(2,4)这一对后输出
(
1
,
3
)
(1,3)
(1,3)这一对。由于
c
2
≥
c
4
c_2 \geq c_4
c2≥c4 所以在输出这一对时先输出 2 后输出 4,由于
c
3
≥
c
1
c_3 \geq c_1
c3≥c1所以在输出这一对时先输出 3 后输出 1。
数据范围与提示
分析
初中数学题。
先排序(从小到大或从大到小皆可),然后从两边到中间依次选择结对对象,即对于第 i i i 个入,TA的帮扶对象为第 n − i + 1 n-i+1 n−i+1 个入。然后再算出答案即可。
如何证明?考虑当 n = 4 n=4 n=4 时, c 1 ≤ c 2 ≤ c 3 ≤ c 4 c_1\le c_2\le c_3\le c_4 c1≤c2≤c3≤c4,考虑所有组合对答案的贡献,使用作差法易证 c 1 c_1 c1 与 c 4 c_4 c4, c 2 c_2 c2 与 c 3 c_3 c3 结对的贡献是最大的。同理,可推得 n n n 更大的情况。
然后就是如何输出方案。显然,组合 ( i , n − i + 1 ) (i,n-i+1) (i,n−i+1) 的贡献要比 ( i + 1 , n − i − 1 + 1 ) (i+1,n-i-1+1) (i+1,n−i−1+1) 的贡献大,所以按从两边到中间的顺序输出即可。
还有一点特别重要,答案的值可能超过 long long 的范围,需要 unsigned long long(卡了我一个小时QWQ)。
具体细节见代码
#include<bits/stdc++.h>
using namespace std;
#define int unsigned long long
const int N=2e5+5;
int n,flag,ans;
struct pl{
int c,id;
}a[N];
bool cmp(pl x,pl y){
return x.c<y.c;
}
signed main()
{
cin>>n>>flag;
for(int i=1;i<=n;i++){
cin>>a[i].c;
a[i].id=i;
}
sort(a+1,a+1+n,cmp);
int l=1,r=n;
while(l<=r){
ans=ans+(a[r].c-a[l].c)*(a[r].c-a[l].c);
l++;
r--;
}
cout<<ans<<"\n";
if(flag){
l=1,r=n;
while(l<=r){
cout<<a[r].id<<" "<<a[l].id<<"\n";
l++,r--;
}
}
return 0;
}