暑假的最后一次萌新联赛,郑大的出题还是比其他学校的难些的。不像之前的几场有特别简单的签到题。题目还是比较不错的。
装备二选一
题意:输入四个值a,b,c,d;分别代表原来武器的暴击率,暴击伤害翻几倍。boss掉落的武器的暴击率,暴击伤害翻几倍。
问是否换boss掉落的武器伤害更高。
因为由题意可以知道伤害翻的倍数可以为1,但是当c,d为1的时候就相当于没有换,所以我们把c,d的值都减去1再相乘进行判断。
#include <bits/stdc++.h>
using namespace std;
int main () {
int a,b,c,d;
cin>>a>>b>>c>>d;
if (a*(b-1)<c*(d-1)) cout<<"YES"<<'\n';
else cout<<"NO"<<'\n';
}
赛时我一直想的是如果暴击率不是100的话,那么就可能一直不暴击,所以就直接判断是不是100再进行c,d的值进行判断。然后就一直没有过。现在看来似乎不是这样的。
百变马喽
题意:给出两个字符串s,t。s比t长度小1。问能否往s里面插入一个字符使两个字符串完全相等。输出能插入的个数并输出位置和要插入的字符。
思路:
- 如果一个字符串插入一个字符就能和另一个字符串完全相等,那么这两个字符串的每个字符出现的次数只有一个不一样。我们就用map来看看是否只有一个字符出现的次数是不一样的。
- 然后我们遍历长的字符串t,当出现的第一个不一样的字符就是我们要插入的字符。
- 统计能插入多少位置,观察后可以发现,能插入的位置取决于有多少一样的字符
例如 abcdeef和abcdeeef要插入的字符是e,字符串s中出现了两个e所以就能插入三个位置。整理输出即可
void solve () {
string s,t;cin>>s>>t;
map<char,int>mp1,mp2;
for (int i=0;s[i];i++) mp1[s[i]]++;
for (int i=0;t[i];i++) mp2[t[i]]++;
char pos;int ans=1;int q;int g=0;
for (int i=0;i<=25;i++) {
char ch = i+'a';
if (mp1[ch]!=mp2[ch]&&g==0) {
g=1;
}
else if (mp1[ch]!=mp2[ch]) {
cout<<"0"<<'\n';return;
}
}
int cnt=0;
for (int i=0;t[i];i++) {
if (s[i]!=t[i]) {
pos=t[i];cnt=i;break;
}
}
for (int i=cnt-1;i>=0;i--) {
if (s[i]==pos) ans++;
else break;
}
cout<<ans<<'\n';
for (int i=cnt-ans+1;i<=cnt;i++) {
cout<<i<<' '<<pos<<'\n';
}
}
追寻光的方向
题意:给出一串序列,小明想要从1跑到n,期间
a
i
a_i
ai的值为小明往后ai个长度找到一个最大值然后休息。问整个过程小明休息几次
思路:这题没有难度,直接根据题意来写就行。数据也比较水,暴力就直接能过
void solve () {
int n;cin>>n;
for (int i=1;i<=n;i++) {
cin>>a[i];
}
int ans=0;
for (int i=1;i<=n;) {
int pos;
int ma=0;
int x=i+a[i];
if (x>n) x=n;
for (int j=i+1;j<=x;j++) {
if (ma<a[j]) {
ma=a[j];
pos=j;
}
}
i=pos;
if (i==n) break;ans++;
}
cout<<ans;
}
四散而逃
题意:给出一个序列,
a
i
a_i
ai表示这一点的人数(2,n-1)之中的人都要逃到1或者n这个地方,每次只能往两边输送两个人,最少几次能输送完。如果送不完输出-1
思路:题目说了每次只能输送两个人,不难想到当人数是奇数的时候就不能输送完,这时就要别的地方的人讲人送到奇数的地方我们才能将这一点的人送完。
我们统计一下奇数和偶数的个数,如果没有偶数个的人的话,我们一定是送不完的,这时输出-1,然后我们把所有的奇数当成比它大一的偶数,后续直接遍历除以2就行了
void solve () {
int n;cin>>n;
int x=0,y=0;
for (int i=1;i<=n;i++) {
cin>>a[i];
if (i>1&&i<n) {
if (a[i]&1) x++;
else y++;
}
}
if (y==0) {
cout<<"-1"<<'\n';return;
}
int ans=0;
for (int i=2;i<=n-1;i++) {
if (a[i]&1) {
ans+=(a[i]+1)/2;
}
else ans+=a[i]/2;
}
cout<<ans;
}
等公交车
题意:给出长度为n,m的两个序列a,b,分别代表与站点的距离,公交车发出的时刻。然后给出q次询问。每次询问时有一个时间和站点。问每一次最少等车时间是多少。
我们模拟样例就会明白样例的意思。就会发现第m辆公交车到达第n个站点的时间为b[m]+a[n]。每次询问的时间点和站点x,y。如果最后一辆车都坐不上的话就等不到公交车输出“TNT”(🐎➕7的团队),换算成公式就是a[y]+b[m]<x,如果不满足这个坐不上车的就直接遍历一下时间点,然后判断即可。写成代码就是
for (int i=1;i<=m;i++) {
int pos = a[y]+b[i];
if (pos>=x) {
cout<<pos-x<<'\n';break;
}
}
下面看完整代码
void solve () {
int n,m;cin>>n>>m;
for (int i=1;i<=n;i++) cin>>a[i];
for (int i=1;i<=m;i++) cin>>b[i];
int q;cin>>q;
while (q--) {
int x,y;cin>>x>>y;
if (a[y]+b[m]<x) {
// cout<<a[y]+b[m]<<' ';
cout<<"TNT"<<'\n';
}
else {
for (int i=1;i<=m;i++) {
int pos = a[y]+b[i];
if (pos>=x) {
cout<<pos-x<<'\n';break;
}
}
}
}
}
24点
题意:在扑克牌中抽四张牌,问随意加减乘除能否构成24
思路:将输入的字符转为合法的数字存在数组里面,再通过DFS和全排列暴力实现。这里要注意除法这里是数学运算
#include<bits/stdc++.h>
using namespace std;
unordered_map<string, int> m = {
{"A", 1}, {"2", 2}, {"3", 3}, {"4", 4}, {"5", 5},
{"6", 6}, {"7", 7}, {"8", 8}, {"9", 9}, {"10", 10},
{"J", 11}, {"Q", 12}, {"K", 13}
};
bool c(vector<double> n) {
if (n.size() == 1) return abs(n[0] - 24) < 1e-6;
for (int i = 0; i < n.size(); ++i)
for (int j = 0; j < n.size(); ++j)
if (i != j) {
vector<double> r;
for (int k = 0; k < n.size(); ++k)
if (k != i && k != j) r.push_back(n[k]);
for (int op = 0; op < 4; ++op) {
if (op < 2 && i > j) continue;
switch (op) {
case 0: r.push_back(n[i] + n[j]); break;
case 1: r.push_back(n[i] * n[j]); break;
case 2: r.push_back(n[i] - n[j]); break;
case 3: if (n[j] != 0) r.push_back(n[i] / n[j]); break;
}
if (c(r)) return true;
r.pop_back();
}
}
return false;
}
int main() {
int t;
cin >> t;
while (t--) {
vector<double> v(4);
for (int i = 0; i < 4; ++i) {
string s;
cin >> s;
v[i] = m[s];
}
sort(v.begin(), v.end());
do {
if (c(v)) {
cout << "YES" << endl;
break;
}
} while (next_permutation(v.begin(), v.end()));
if (!c(v)) cout << "NO" << endl;
}
return 0;
}