ZZULIOJ
分析和思路以及代码 持续更新中
问题 A: 简单的小游戏1
分析:
模拟,如果之前就存在2048这个数的话 就直接输出yes,没有的话就去枚举2的次方,看看这个数有没有,有的话,个数是不是大于2的,要是大于2了 我就去合成 合成的个数就给当前这个数*2
代码:
#include<bits/stdc++.h>
#define _for(i, a, b) for(int i = a; i <= b; ++ i )
using namespace std;
const int N = 2e5 + 10;
int a[N];
int n, m;
string s;
signed main() {
int t;
cin >> t;
while(t--) {
cin >> n;
map<int, int>mp;
mp[2048] = 0;
bool flag = false;
_for(i, 1, n) {
cin >> a[i];
if(a[i] == 2048) {
flag = true;
}
mp[a[i]]++;
}
if(flag) {
cout << "yes" << endl;
} else {
for(int i = 0; i <= 10; ++ i ) {
int tt = pow(2, i);
if(mp[tt] >= 2) {
int gs = mp[tt] / 2;
mp[tt] %= 2;
mp[2 * tt] += gs;
}
}
if(mp[2048]) {
cout << "yes" << endl;
} else {
cout << "no" << endl;
}
}
}
return 0;
}
问题 B: 简单的小游戏2
分析:
也是一个枚举的题,但是需要注意的是k太大了,我们注意到,l和r并不大,因此是会出现循环的,几次一循环呢?(r - l + 1) 因此我们可以拿k进行取余一下,减少时间
代码:
#include<bits/stdc++.h>
#define _for(i, a, b) for(int i = a; i <= b; ++i)
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
const int N = 2e5 + 10;
int a[N];
int n, m;
string s;
void move(int l, int r) {
char p = s[r];
for(int i = r; i >= l; -- i ) {
s[i] = s[i - 1];
}
s[l] = p;
}
signed main() {
IOS;
cin >> s;
int q;
cin >> q;
while(q--) {
int l, r, k;
cin >> l >> r >> k;
//必须要去优化k去进行取余
l--, r--;
int t = (r - l + 1);
k %= t;
while(k--) {
move(l, r);
}
}
cout << s << endl;
return 0;
}
问题 C: 购物的小a
分析:
这个题气死我了,是小学的知识吗? 刚开始的理解就出了问题. 举个例子,比如 这个数是大于1000的,那么100到300这个区间就会去便宜(300-100)*0.9 而不是(x-100)*0.9 其他同理,还要加个特判,要是这个代金券m是大于n的,我就直接输出0了,不用再去打折什么的了,其他的情况是 这代金券是用还是不用呢? 要是用的话,必须在打折之前用 也就是代码里面的 youhui(n - m),要是不用的话 就直接youhui(n),取最小的即可
代码:
#include<bits/stdc++.h>
#define y1 Y1
#define fi first
#define endl "\n"
#define se second
#define PI acos(-1)
#define int long long
#define pb(x) push_back(x)
#define PII pair<int, int>
#define Yes cout << "Yes\n";
#define No cout << "No\n";
#define YES cout << "YES\n";
#define NO cout << "NO\n";
#define _for(i, a, b) for(int i = a; i <= b; ++i)
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
const int N = 2e5 + 10;
int a[N];
double n, m;
string s;
int youhui(double x) {
double t = 0;
int p = x;
if(x <= 100) {
return x;
} else if(x <= 300) {//100 - 300
t += 100 + (x - 100) * 0.9;
} else if(x <= 500) {
t += 100 + (300- 100) * 0.9 + (x - 300) * 0.85;
} else if(x <= 800) {
t += 100 + (300 - 100) * 0.9 + (500 - 300) * 0.85 + (x - 500) * 0.8;
} else if(x <= 1000) {
t += 100 + (300 - 100) * 0.9 + (500 - 300) * 0.85 + (800 - 500) * 0.8 + (x - 800) * 0.75;
} else if(x > 1000){
t += 100 + (300 - 100) * 0.9 + (500 - 300) * 0.85 + (800 - 500) * 0.8 + (1000 - 800) * 0.75 + (x - 1000) * 0.7;
}
return (int)t;
}
signed main() {
//代金券只能在 打折之前 使用
int ret = 1e20;
cin >> n >> m;
if(m >= n) {//ret保证是非负的
cout << 0 << endl;
return 0;
}
//代金券 用还是不用
//1 不用
ret = min(ret, youhui(n));
//用
ret = min(ret, youhui(n - m));
cout << ret << endl;
return 0;
}
问题 D: 有趣的信息
分析:
读题是真的重要啊, 比赛的时候读错题了 无语 今天补题的时候 又读了一遍题 才发现还是蛮简单的, 但是有一个细节需要注意到,就是 在没操作之前 还需要统计一下他的'x'这个数量是不是大于k的 要是大于k的话 还要++
代码:
#include<bits/stdc++.h>
#define y1 Y1
#define fi first
#define endl "\n"
#define PI acos(-1)
#define int long long
#define pb(x) push_back(x)
#define PII pair<int, int>
#define Yes cout << "Yes\n";
#define No cout << "No\n";
#define YES cout << "YES\n";
#define NO cout << "NO\n";
#define _for(i, a, b) for(int i = a; i <= b; ++i)
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
const int N = 2e5 + 10;
int a[N];
int n, k, t;
string s;
unordered_map<char, int>mp;//每个字符 在s里面出现的次数
char zh(char x) {
if(x == 'Z')return 'A';
if(x == 'z')return 'a';
return (char)(x + 1);
}
signed main() {
IOS;
cin >> s >> n >> k;
bool flag = false;
_for(i, 0, s.size() - 1) {
mp[s[i]]++;
}
if(mp['x'] > k)t++;
//在 操作过程中
//如果 xxx 出现的次数等于或大于 3 次,输出 "xxx * 3" ;
//如果 xxx 出现 1 次,输出 "xxx" ;
//其余情况输出 "None"
while(n--) {
int l, r;
cin >> l >> r;
l--,r--;
for(int i = l; i <= r; ++ i ) {
char prev = s[i];//没转换之前的
mp[prev]--;
s[i] = zh(prev);//转换之后的
mp[s[i]]++;
if(mp['x'] > k) {
t++;
}
if(t >= 3) {
cout << "xxx * 3" << endl;
return 0;
}
}
}
if(t == 1) {
cout << "xxx" << endl;
return 0;
}
cout << "None" << endl;
return 0;
}
问题 E: 喜欢刷b站的学长
分析:
模拟, 也就是给你 两个日期,让你去判断 第一个日期是不是比第二个日期大的, 这个先去判断年份,然后年份有结果了就不用去比较其他的了,要是年份相同的话,就去比较月份 同理依次下去
代码:
#include<bits/stdc++.h>
#define _for(i, a, b) for(int i = a; i <= b; ++i)
using namespace std;
const int N = 2e5 + 10;
int a[N];
int n, m;
signed main() {
//注意 是 这一天
int h1, m1, s1;
cin >> h1 >> m1 >> s1;
int h2, m2, s2;
cin >> h2 >> m2 >> s2;
if(h2 > h1 || (h2 == h1 && m2 > m1) || (h2 == h1 && m2 == m1 && s2 > s2)) {
cout << "YES" << endl;
} else {
cout << "NO" << endl;
}
return 0;
}
问题 F: 不会Dynamic Programming怎么办
分析:
方法一:
这个题是有规律的,当然也是可以去暴力的 直接去从a到b去枚举 看看他是<10的话 就是一个数 就加一,要是<100的话就是两位数,要是<1000就是3位数, 不要用while去判断他的位数,是会TLE的
方法二:
举个例子让你求9到100之间的, 我的思路是先求9他这个位数是1为 然后最大的1位数是9 9到9之间有一个数也就是(9 - 9 + 1) * 1(这个1是位数) 然后100是3位的 说明他们之间是存在两位数的 全部的两位数 先看看最小的两位数是10 最大的两位数是99 他们之间的数的个数是(99 - 10 + 1) * 2(位数),乘2的原因是 10到99一共有99-10+1个 每个数贡献两位
代码:
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
int a[N];
int n, m;
string s;
int ws(int x) {//判断这个数 有几位数
int t = 0;
while(x) {
x /= 10;
t++;
}
return t;
}
int ma(int w) {//这个位最大的数
return pow(10, w) - 1;
}
int mi(int w) {//这个位最小的数
return pow(10, w - 1);
}
signed main() {
int l, r, t, tt = 0;
cin >> l >> r >> t;
int ws1 = ws(l);
int ws2 = ws(r);
if(ws1 == ws2) {
tt = (r - l + 1) * ws1;
} else {
tt += (ma(ws1) - l + 1) * ws1;
for(int i = ws1 + 1; i <= ws2 - 1; ++ i ) {
tt += (ma(i) - mi(i) + 1) * i;
if(tt > t) {
cout << "nizhenlihai!" << endl;
return 0;
}
}
tt += (r - mi(ws2) + 1) * ws2;
}
if(tt == t) {
cout << "nizhenlihai!" << endl;
} else {
cout << "laji" << endl;
}
return 0;
}
问题 G: 小F和小G
分析:
G题重测被挂掉了 , 有点难啊
要快速获取里面的有用信息, 大致的意思就是给你两个字符串s1, s2, 你去交换s1串里面的字符,然后尽量让s1和s2一样, 问最后最少有多少个实在对不上的 用两个数组 一个去统计s1的 一个去统计s2里面的字符, 然后看看他们对应的字符的差距 记得答案要除以2 ,因为s1里面和s2里面都会去贡献不同的字符
代码:
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
int n, m;
string s;
int a[27], b[27];
signed main() {
cin >> n;
string s1;
cin >> s1;
string s2;
cin >> s2;
for(int i = 0; i < n; ++ i ) {
a[s1[i] - 'a']++;
b[s2[i] - 'a']++;
}
int ret = 0;
for(int i = 0; i < 26; ++ i ) {
ret += abs(a[i] - b[i]);
}
cout << ret / 2 << endl;
return 0;
}
问题 H: X学长
分析:
这个题 就凸显出了 c++里面的substr了,可以看看我之间对他的简介哈, 这个是截取字符串的,第一个参数是起始位置,第二个是你要截取的个数,也是简单题,我用的是map去存每个字符串的里面的出生年的信息
s2.substr(6, 4)
然后看看他的个数是不是为1 要是为1的话 就说明没人和他同一年 然后就输出 年龄最大的 ,要是有和他出生年份是一样的话 就输出一样的个数 也就是mp[s2.substr(6, 4)]
怎么去求年龄最大的呢? 注意年龄大 说明他的 年 月 日份小 1998是比1999年出生的早的
代码:
#include<bits/stdc++.h>
#define endl "\n"
#define se second
#define PI acos(-1)
#define int long long
#define pb(x) push_back(x)
#define PII pair<int, int>
#define Yes cout << "Yes\n";
#define No cout << "No\n";
#define YES cout << "YES\n";
#define NO cout << "NO\n";
#define _for(i, a, b) for(int i = a; i <= b; ++i)
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
const int N = 2e5 + 10;
int a[N];
int n;
string s;
int ret = 0;
map<string, int>mp;
pair<string, string>p[110];
int y = 99999, m = 999, d = 999;
int zh(string t) {
int p = 0;
for(int i = 0; i < t.size(); ++ i ) {
p = p * 10 + (t[i] - '0');
}
return p;
}
signed main() {
IOS;
cin >> n;
_for(i, 1, n) {
string s1, s2;
cin >> s1 >> s2;
mp[s2.substr(6, 4)]++;
ret = max(ret, mp[s2.substr(6, 4)]);
p[i] = {s1, s2};
}
if(ret == 1) {
int jl = 1;
_for(i, 1, n) {
s = p[i].se;
int yy = zh(s.substr(6, 4));
int mm = zh(s.substr(10, 2));
int dd = zh(s.substr(12, 2));
bool flag = false;
if(yy < y) {
flag = true;
}
if(yy == y && mm < m) {
flag = true;
}
if(yy == y && mm == m && d < dd) {
flag = true;
}
if(flag) {
y = yy;
m = mm;
d = dd;
jl = i;
}
}
cout << p[jl].fi << " " << p[jl].se << endl;
} else {
cout << ret << endl;
}
return 0;
}
问题 I: 你与女神共进晚餐
分析:
提取信息依然是很重要的, 这个题就是让你求每行的最小值 然后 这些最小值里面的最大值 就ok了
代码:
#include<bits/stdc++.h>
#define y1 Y1
#define fi first
#define endl "\n"
#define se second
#define PI acos(-1)
#define int long long
#define pb(x) push_back(x)
#define PII pair<int, int>
#define Yes cout << "Yes\n";
#define No cout << "No\n";
#define YES cout << "YES\n";
#define NO cout << "NO\n";
#define _for(i, a, b) for(int i = a; i <= b; ++i)
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
const int N = 2e5 + 10;
int a[1010][1010];
int n, m;
string s;
signed main() {
IOS;
int ret = 0;
cin >> n >> m;
_for(i, 1, n) {
int t = 0x3f3f3f3f;
_for(j, 1, m) {
cin >> a[i][j];
t = min(a[i][j], t);
}
ret = max(ret, t);
}
cout << ret << endl;
return 0;
}
问题 J: 公交车上的座
分析:
也是模拟,自己可以去模拟一下 先后顺序 注意一下就可以了
代码:
#include<bits/stdc++.h>
#define y1 Y1
#define fi first
#define endl "\n"
#define se second
#define PI acos(-1)
#define int long long
#define pb(x) push_back(x)
#define PII pair<int, int>
#define Yes cout << "Yes\n";
#define No cout << "No\n";
#define YES cout << "YES\n";
#define NO cout << "NO\n";
#define _for(i, a, b) for(int i = a; i <= b; ++i)
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
const int N = 2e5 + 10;
int n, m;
string s;
int a[1010][5];
vector<int>v(10010);
signed main() {
IOS;
cin >> n >> m;
//先排吧
bool flag = false;
int t = 1;
for(int i = 1; i <= n; ++ i ) {
a[i][1] = t++;
m--;
if(m == 0)break;
a[i][4] = t++;
m--;
if(m == 0)break;
}
if(m) {
for(int i = 1; i <= n; ++ i ) {
a[i][2] = t++;
m--;
if(m == 0)break;
a[i][3] = t++;
m--;
if(m == 0)break;
}
}
for(int i = 1; i <= n; ++ i ) {
if(a[i][2] != 0)
cout << a[i][2] << ' ';
if(a[i][1] != 0)
cout << a[i][1] << ' ';
if(a[i][3] != 0)
cout << a[i][3] << ' ';
if(a[i][4] != 0)
cout << a[i][4] << ' ';
}
return 0;
}