A.赌场风云Ⅰ
题目描述
17张牌你能秒我??你能秒杀我??17张牌你今天能把我卢本伟秒了,我当场就把这个电脑屏幕吃掉 !! —赌怪
”当年陈刀仔他能用20块赢到3700万,我mcc用100块赢到2000万,不是问题,请叫我赌魔!!“,沉迷于手机斗地主的mcc夸下海口说。
由于一次意外,mcc的手机屏幕磕坏了,看不见斗地主欢乐豆的余额,但是可以知道每次牌局的盈亏情况。可是已经上头的mcc算不清到底赢了多少,身为他的好朋友,请你帮帮他,看看他是否能够完成夸下的海口。如果可以完成,就高呼“You are dumo!!”,否则就狠狠的嘲讽“You are cishanjia”。
输入
第一行输入一个整数n,表示进行的牌局数量(1<=n<=1e5)
第二行输入n个整数,表示每局获得欢乐豆的数量ai,单位为万(可能为负数,-1e3<=ai<=1e3)
输出
如果获得的欢乐豆总数量不少于2000万,输出“You are dumo!!”
否则,输出“You are cishanjia”,结果不包含引号
样例输入
2
1000 1000
样例输出
You are dumo!!
提示
样例中将每局获得的欢乐豆数量相加正好等于2000万,所以输出“You are dumo!!”
代码
本题为签到题,只需要将所有数加起来,和2000比较即可
#include<bits/stdc++.h>
using namespace std;
int main(){
int n;
cin>>n;
int sum=0;
for(int i=1;i<=n;i++){
int num;
cin>>num;
sum+=num;
}
if(sum>=2000) cout<<"You are dumo!!";
else cout<<"You are cishanjia";
return 0;
}
B.赌场风云Ⅱ
题目描述
经过一个寒假的磨砺,mcc已经将麻将掌握的炉火纯青。一天,mcc邀请lsh、wsh、wyk一起打麻将,可是晕晕的wsh算不清自己每局该给多少卡片(筹码)。已知麻将的各个座位编号为1,2,3,4,四位学长按进来的顺序依次落座。每盘麻将结算的规则为:
-
非庄家胡牌,庄家给胡牌者两个卡片,其余人给胡排者一个卡片
-
庄家胡牌,剩下的三人一人给庄家两个卡片
-
每局的获胜者下局为庄家,第一局由编号为1座位上的人为庄家
-
每人的初始卡片数量为10张
现在给你四人进入房间的顺序,和每盘的胡牌者所坐位置的编号,请你帮一帮wsh算一算每盘游戏后剩余的卡片数量
输入
第一行包含两个整数n,m,代表游戏进行的盘数和wsh所在位置的编号(1<=n<=1e5,1<=m<=4)
第二行输入n个整数ai,代表每盘游戏胡牌者的编号(1<=ai<=4)
输出
仅一行,包含n个整数,表示每盘麻将过后wsh剩余的卡片数量(卡片剩余数量可能为负数)
样例输入
4 2
1 1 2 2
样例输出
8 6 10 16
提示
第一盘,1号为庄家,1号胡牌,所以每人给庄家2张卡片,此时2号剩余8张
第二盘,1号为庄家,1号胡牌,所以每人给庄家2张卡片,此时2号剩余6张
第三盘,1号为庄家,2号胡牌,所以庄家给2号2张卡片,3、4号分别给2号1张卡片,庄家由1号变为2号,此时2号剩余10张
第一盘,2号为庄家,2号胡牌,所以每人给庄家2张卡片,此时2号剩余16张
代码
本题是个小模拟
共五种情况
1.wsh胡牌,且为庄家
2.wsh胡牌,但不为庄家
3.非wsh胡牌,但wsh为庄家
4.非wsh胡牌,但获胜的是庄家
5.非wsh胡牌,且获胜的不为庄家
#include<bits/stdc++.h>
using namespace std;
int main(){
int n,m;
scanf("%d %d",&n,&m);
int cur = 10;
int pre = 1;
for(int i=1;i<=n;i++){
int num;
scanf("%d",&num);
if(num == m){
if(num == pre) cur+=6;
else cur+=4;
}
else {
if(num == pre) cur-=2;
else {
if( pre == m){
cur-=2;
}
else cur-=1;
}
}
pre = num;
printf("%d ",cur);
}
return 0;
}
C.博弈,我要狠狠的博弈
三十年河东,三十年河西,莫欺少年穷。麻将游戏以lsh只赢了第一把落幕,输麻了的lsh势必要赢mcc一次,因此他提出了和mcc玩一个游戏,游戏规则如为,有n个石子堆,每个石子堆里石子的个数为ai,两人轮流挑选一个石子堆并将其分为两份,每一份至少有一个石子,最后无法操作的人失败,另一人为胜者,由于是lsh提出的游戏,所以lsh先手。聪明的mcc已经猜到在某些情况下先手必定会获得胜利,请你帮助mcc识破lsh的阴谋诡计。
输入
第一行包含一个整数n,代表石子堆的个数(1<=n<=50)
第二行包含n个整数,代表每堆石子的个数ai(1<=ai<=50)
输出
如果先手必胜,输出“I've seen through your plot”
否则输出“Dishes are practiced more”,结果不包含引号
样例输入
4
1 1 1 2
样例输出
I've seen through your plot
提示
lsh第一步选择第四堆,将其分成1和1,此时所有石子堆均为1,mcc无法操作,先手必胜
代码
本题类似于博弈论,根据题面可以知道,最后所有石子堆里石子的数量都为1时,就无法操作了,每一堆石子可以进行的操作数为ai-1,累加后对2进行取模,余数为1则先手必胜,余数为0则后手必胜
#include<bits/stdc++.h>
using namespace std;
int main(){
int n;
cin>>n;
int sum = 0;
for(int i=1;i<=n;i++){
int num;
cin>>num;
sum+=(num-1);
}
if(sum%2) cout<<"I've seen through your plot";
else cout<<"Dishes are practiced more";
}
D.飞驰人生
题目描述
炎热的夏天,mcc同学在看完《飞驰人生》这部作品后,不顾天气的残酷,也要考出驾照,像张弛一样飞驰巴音布鲁克,但要考出驾照,方向盘的正确转动是不可缺少的,mcc同学认真的将教练所讲全部记下,并且简化理解为以下几种操作:分别为前进,倒车,左一(表示向左一格),左二(表示向左两格),右一(表示向右一格),右二(表示向右两格)。
下面mcc同学将对这些操作进行实操。在n*m的场地内,给定mcc的起始坐标x,y,以及进T次操作,在给定的操作指令中,有三个命令Q,P,K。Q有两种,分别是前进(U)和倒车(D),P为向左(L)或向右(R),K为0,1,2;0就是不进行左右移操作,1表示左一或右一,2表示左二或右二。请问在进行完T次操作后,MC的坐标,若超出场地的大小,则输出"Wrong Order!"。
题目规定:y轴正方向为前进,负方向为后退,x轴正方向为向右,x轴负方向为向左。
输入
第一行为场地的大小n,m(0<=n<=1e4, 0<=m<=1e4);
第二行为起始坐标x,y以及指令数T;
第三行为T行三个指令Q,P,K(Q,P为字符,0<=K<=2);
输出
输出共一行,两个整数表示最终坐标或者"Wrong Order!",结果不包含引号
样例输入
3 3
1 1 3
U R 1
D L 0
U R 1
样例输出
3 2
提示
进行三步操作,第一步U R 1 ,也就是向前走一格,向右一格也就是y+1,x+1;
第二步D L 0 也就是y-1,x不变;
第三步U R 1 y+1,x+1;
代码
本题为模拟,根据输入改变当前位置的值,最后判断是否在场地内即可
#include<bits/stdc++.h>
using namespace std;
int main() {
int n, m;
cin >> n >> m;
int x, y, T;
cin >> x >> y >> T;
while (T --) {
char Q, P;
int K;
cin >> Q >> P >> K;
if (Q == 'U') {
if (P == 'L') {
if (K == 0) {
y += 1;
}
if (K == 1) {
y += 1;
x -= 1;
}
if (K == 2) {
y += 1;
x -= 2;
}
} else if (P == 'R') {
if (K == 0) {
y += 1;
}
if (K == 1) {
y += 1;
x += 1;
}
if (K == 2) {
y += 1;
x += 2;
}
}
} else if (Q == 'D') {
if (P == 'L') {
if (K == 0) {
y -= 1;
}
if (K == 1) {
y -= 1;
x -= 1;
}
if (K == 2) {
y -= 1;
x -= 2;
}
} else if (P == 'R') {
if (K == 0) {
y -= 1;
}
if (K == 1) {
y -= 1;
x += 1;
}
if (K == 2) {
y -= 1;
x += 2;
}
}
}
}
if (x < 0 || x > n || y < 0 || y > n) {
cout << "Wrong Order!" << endl;
} else cout << x << ' ' << y << endl;
return 0;
}
E.植物大战僵尸杂交版之怒火辣椒
题目描述:
最近wyk沉迷于植物大战僵尸杂交版的抽奖盒子模式,每次在僵尸没来的时候抽到与火爆辣椒杂交
的植物都十分懊恼,于是他幻想有这样一种辣椒植物:该植物在生成时会随机生成一个怒气值,每
出现一个僵尸,它会立即击败这个僵尸,并衰减与这个僵尸血量相同的怒气值,若该植物的怒气值
严格小于当前出现的僵尸,那么它将直接死亡。wyk想知道对于给定怒火的该植物能击败多少僵尸,但它并不会计算,想请你帮忙计算出并告诉他。
输入:
第一行输入两个整数n,q(1<=n,q<=1e5),分别表示僵尸的数量和wyk询问的次数。
第二行输入n个整数ai,代表第i个僵尸的血量(1<=ai<=1e9,1<=i<=n)。
接着q行,每行一个x(1<=x<=1e18)表示对于当次询问该植物的怒气值。
输出:
共q行,每行一个整数代表每次询问的答案
输入样例:
5 4 4 6 3 7 2 10 11 30 3
输出样例:
2 2 5 0
代码:
本题的暴力写法为双重循环,但n,q的最大值都为1e5,双重循环明显会时间超限,所以我们用前缀和+二分查找优化掉第二层循环,此时的时间复杂度为O(n*log2n),但是本题的输入输出在极限情况下达到了3e5,cin/cout的效率要明显低于scanf/printf,所以卡掉了cin/cout,由于endl每一次都要刷新缓冲,所以效率也要低于\n,也就是说仅仅关流是不够的,这也就是我们常说的卡常。
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e5 + 10;
int a[N];
int n, q;
signed main() {
scanf("%d %d",&n,&q);
for (int i = 1; i <= n; i++) {
scanf("%d",&a[i]);
a[i] += a[i - 1];
}
while (q--) {
int x;
scanf("%d",&x);
int l = 0, r = n;
while (l < r) {
int mid = (l + r + 1) / 2;
if (a[mid] > x)r = mid - 1;
else l = mid;
}
printf("%d\n",l);
}
return 0;
}
F.min 和 gcd
题目描述:
出题人不喜欢数学,所以他决定把这个问题交给你。
对于一个数组的连续区间[l,r],如果min(al,al+1,......,ar)=gcd(al,al+1,......,ar),则称这个区间为好区间。他将给你一个数组,需要你求出数组中的好区间的长度。
min(al,al+1,......,ar)表示区间(l,r)中的最小元素,gcd(al,al+1,......,ar)表示区间(l,r)所有元素的最大公约数。特别的,规定区间的长度为1的gcd(ai)等于其本身。
输入:
第一行包含一个整数n(1<=n<=1e5),代表数组长度。
第二行包含n个整数ai(1<=ai<=1e6),表示他给你的数组。
输出:
对于每个样例输出一个数,为好区间的长度。
输入样例:
5 6 2 7 4 9
输出样例:
2
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int a[N];
int n;
int main(){
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
int res=1;
for(int i=1;i<=n;i++){
int cnt=1;
int l,r;
for(r=i+1;r<=n;r++){
if(a[r]>=a[i]&&a[r]%a[i]==0)cnt++;
else break;
}
for(l=i-1;l>0;l--){
if(a[l]>=a[i]&&a[l]%a[i]==0)cnt++;
else break;
}
i=r-1;
res=max(res,cnt);
}
cout<<res;
return 0;
}
G.max 和 gcd
题目描述:
出题人不喜欢数学,所以他决定把这个问题交给你。
对于一个数组的连续区间[l,r],如果max(al,al+1,......,ar)=gcd(al,al+1,......,ar),则称这个区间为好区间。他将给你一个数组,需要你求出数组中的好区间的长度,以及该好区间的gcd(al,al+1,......,ar)的值。
max(al,al+1,......,ar)表示区间[l,r]中的最大元素,gcd(al,al+1,......,ar)表示区间[l,r]所有元素的最大公约数。特别的,规定区间的长度为1的gcd(ai)等于其本身。
输入:
第一行包含一个整数n(1<=n<=1e5),代表数组长度。
第二行包含n个整数ai(1<=ai<=1e9),表示他给你的数组。
输出:
对于每个样例输出一行两个数,第一个为好区间的gcd(al,al+1,......,ar),第二个为好区间的长度
注意:若有多个好区间的长度相同,应输出gcd(al,al+1,......,ar)最大的那个。
输入样例:
2
1 2
输出样例:
2 1
说明:
max(a1,a2)为2,gcd(a1,a2)1;max(a1)为1,gcd(a1)为1;max(a2)为2,gcd(a2)为2。故区间[1,1]和区间[2,2]都是好区间且最大gcd为2,所以输出2 1。
代码:
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int a[N];
int n;
int main() {
cin >> n;
for (int i = 1; i <= n; i++)cin >> a[i];
int last = -1, len = 1;
int res = 0, num = 0;
for (int i = 1; i <= n; i++) {
if (a[i] != last) {
last = a[i];
len = 1;
} else len++;
if (len > res) {
num = a[i];
res = len;
} else if (len == res) {
num = max(num, a[i]);
}
}
cout << num << " " << res;
return 0;
}
H.魔法猫猫将拯救世界
题目描述
在植物大战僵尸杂交版中,黑暗僵尸的传送门在两个世界的交界处打开了,现在整个世界都面临着可怕的威胁。为了关闭传送门,拯救世界,你需要打败一个又一个从传送门中出现的n个僵尸。
只有魔法西瓜猫猫才能做到这一点。她拥有两种魔法能力--冰西瓜魔法和火西瓜魔法。在一秒钟内,猫猫可以产生w单位的冰法力和 f单位的火法力。她需要法力值来施法。最初猫猫有0个单位的冰系法力值和0个单位的火系法力值。
每个从传送门中出现的n个僵尸都有自己的力量,用正整数表示。要打败强度为si的i个僵尸,猫猫需要施放至少相同强度的冰西瓜魔法或火西瓜魔法。换句话说,猫猫至少可以花费si个单位的冰系法力值在冰西瓜魔法上,或者至少花费si个单位的火系法力值在火西瓜魔法上。
猫猫可以瞬间创造并施放西瓜魔法。只要有足够的法力值,猫猫每秒可以施放不限数量的西瓜魔法。
猫猫想要尽快拯救世界,请告诉她需要多少时间。
输入格式
第一行包含两个整数w,f(1<=w,f<=1e9)猫猫每秒可产生的冰与火法力值。
第二行包含一个整数n(1<=n<=100)僵尸数量。
第三行包含n个整数s1,s2,s3,,,,,,sn(1<=si<=1e4)僵尸的强度。
输出格式
对于每个测试用例,输出一个整数-猫猫打败所有僵尸所需的最短时间(以秒为单位)。
样例输入
2 3 3 2 6 7
样例输出
3
样例解释
在第一个样本中,在第一秒之后,猫猫可以消耗2单位的火法力值来杀死第一个僵尸。然后,她有2单位的冰法力值和1单位的火法力值。第三秒后,她将拥有6单位的冰法力值和7单位的火法力值。这足以立即杀死第二只和第三只僵尸。故输出3。
代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
signed main() {
int q;
cin >> q;
while (q--) {
int w, f, n;
cin >> w >> f >> n;
vector<int> s(n);
int sum_s = 0;
for (int i = 0; i < n; ++i) {
cin >> s[i];
sum_s += s[i];
}
vector<bool> dp(sum_s + 1);
dp[0] = true;
for (int i = 0; i < n; ++i) {
for (int w = sum_s; w - s[i] >= 0; --w) {
dp[w] = dp[w] || dp[w - s[i]];
}
}
int ans = 2e9;
for (int i = 0; i <= sum_s; ++i) {
if (dp[i]) {
ans = min(ans, max((i + w - 1) / w, (sum_s - i + f - 1) / f));
}
}
cout << ans << "\n";
}
return 0;
}
I.植物大战僵尸杂交版之血战到底
题目描述
最近植物大战僵尸杂交版在网络上非常流行,很多人都在玩这个游戏,且都被这个游戏的残酷次次折磨,尽管每次都玩红温,但他们依旧迎难而上,血战到底。下面是星空同学正在玩的一场植物大战僵尸杂交版的布局,请你根据给定的规则判断他是否能挺过这一波。
游戏规则:在n*m的地图中,每一行存在很多植物和僵尸,一种只能干掉一个普通僵尸的植物,我们称之为普通植物,且还有几种强力植物分别为:向日女王,热狗,军方。
每种植物能干掉的僵尸数量如下:
普植:1;
豆哥:1;
汉堡王:1;
向日女王:2;
热狗:3;
军方:4;
判断一波的输赢的规则:能否把n行的僵尸全部干掉,每种植物干掉僵尸后就会消失,也就是只能消灭掉自己能干掉的僵尸数量。若能全部干掉,则输出Next!,否则则输出GG!
输入格式
第一行为地图的大小n,m(1<=n,m<=1e3)。
下面则是地图内植物与僵尸的分布。
输出格式
一行答案。Next!或GG!
样例输入
5 6 asdfgd queene edjund sskdre ulkgea
样例输出
Next!
样例解释
第一行:根据查表a,d,f为植物,s,g为僵尸所以且植物杀死的僵尸数量大于僵尸的数量第一行能全部干掉;
第二行:由表可知queen能干掉2个僵尸,且这一行也就只有一只僵尸,也就是能全部干掉;
第三行:由表可知植物杀死僵尸数大于等于僵尸数也就是能全部干掉;
第四行:由表可知植物杀死僵尸数大于等于僵尸数也就是能全部干掉;
第五行:由表可知植物杀死僵尸数大于等于僵尸数也就是能全部干掉;
五行全部干掉也就是可以战胜这一波也就是Next!
代码
#include<bits/stdc++.h>
using namespace std;
const int N = 1e4;
int main() {
int n,m;
cin >> n >> m;
string s[N];
for(int i = 0 ; i < n ; i ++ ) {
cin >> s[i];
}
int sum=0;
for(int i = 0 ; i < n ; i ++ ) {
string str = s[i];
string ans = "";
int k_z = 0,cnt_z = 0;
while(str.find("queen")!=-1) {
k_z += 2;
int st =str.find("queen");
int ed = st + 5;
ans += str.substr(0,st);
ans += str.substr(ed);
str = ans;
ans = "";
}
while(str.find("re")!=-1) {
k_z += 3;
int st =str.find("re");
int ed = st + 2;
ans += str.substr(0,st);
ans += str.substr(ed);
str = ans;
ans = "";
}
while(str.find("jun")!=-1) {
k_z += 4;
int st =str.find("jun");
int ed = st + 3;
ans += str.substr(0,st);
ans += str.substr(ed);
str = ans;
ans ="";
}
for(int j = 0; j < str.size(); j ++ )
{
if(str[j] == 'a'||str[j] == 'c'||str[j] == 'd'||str[j] == 'f'||str[j] == 'h'||str[j] == 'i'||str[j] == 'l'||str[j] == 'p'||str[j] == 'u')
{
k_z+=1;
}
if(str[j] == 'b'||str[j] == 'e'||str[j] == 'g'||str[j] == 'k'||str[j] == 'm'||str[j] == 'n'||str[j] == 'o'||str[j] == 's'||str[j] == 't'||str[j] == 'v'||str[j] == 'w'||str[j] == 'x'||str[j] == 'y'||str[j] == 'z')
{
cnt_z +=1;
}
}
if(k_z >= cnt_z)
{
sum++;
}
}
if(sum == n)cout<<"Next!"<<endl;
else cout << "GG!" << endl;
return 0;
}
J.HF插队
题目描述:
国庆假期是一个出去游玩的好时机,但是只有前一天在做完核酸才能够出去,10月2日一大早就有不少人在排队等待做核酸,小Y,小HF,小H三个人都来做核酸,此时队伍中总共有n个人, 他们排在同一队的不同位置。但是,在排队过程中有m个人混水摸鱼,偷偷的插队。之后小H给小Y发消息,问问小Y的位置,如果小Y在小H的前面,那么小Y会毫不犹豫的说:"赶紧来我前面", 但是如果小Y在小H的后面,小Y会委婉的说:"咱们再等等吧"。小HF是个老实人,绝对不会做出插队这种事情,但他在排队过程中闲得没事干,而且手机快没电了,他就开始数小H和自己之间的男生和女生各有多少,你可以帮帮他嘛?
输入:
第一行一个正整数n,表示开始时队伍中的人数 第二行一个长度为n的字符串,'F'表示男生,'M'表示女生 第三行三个正整数,分别表示小Y、小HF、小H三个人开始的位置 第四行一个正整数m,表示插队的人数 接下来的m行,每行一个字符和一个正整数,表示插队的人的性别和插队的位置
2<=n+m<=1e5
输出:
输出最终小HF和小H之间男生和女生的数目
样例输入:
5 FMFFF 1 3 5 3 M 6 M 2 M 3
样例输出:
1 3
提示:
样例解释: 第一次插队后的队列:FMFFFM 第二次插队后的队列:FMMFFFM 第三次插队后的队列:FMMMFFFM 最终队列:FFMMMFFM
代码
#include <iostream>
#include <vector>
#include <string>
using namespace std;
vector<char>q;
string s;
int main() {
int n, m, pos;
char se;
int x1, x2, x3;
cin >> n >> s;
for (int i = 0; i < s.length(); i++) {
q.push_back(s[i]);
}
cin >> x1 >> x2 >> x3;
x1--;
x2--;
x3--;
q[x1] = 'Y'; //小杨
q[x2] = 'H'; //小皇
q[x3] = 'Z'; //小胡
cin >> m;
while (m--) {
cin >> se >> pos;
q.insert(q.begin() + pos - 1, se);
}
int cnt = -1;
for (auto x : q) { //更新位置
++cnt;
if (x == 'Y') {
x1 = cnt;
} else if (x == 'H') {
x2 = cnt;
} else if (x == 'Z') {
x3 = cnt;
}
}
if (x3 > x1) { //说明在我后面
q.erase(q.begin() + x3);
q.insert(q.begin() + x1, 'Z');
x3 = x1;
x1++;
}
int op = 0;
int ans1 = 0, ans2 = 0;
for (auto x : q) {
//cout << x << " ";
if (x == 'H' || x == 'Z') {
op++;
continue;
}
if (op == 1) {
if (x == 'F' || x == 'Y')
ans1++;
else
ans2++;
}
}
//cout << endl;
cout << ans1 << " " << ans2 << endl;
return 0;
}