A
大意:询问序列是否可以通过随意变换顺序后单调递增?
思路:sort后,跑一遍检查是否有相等的就行
例如这种就不行 :1 1 2 2 3 4 7 9
AC代码:
#include <bits/stdc++.h>
#define endl '\n'
using namespace std;
int a[100 + 5];
void solve(){
int n;
cin >> n;
memset(a, 0, sizeof a);
for(int i = 1; i <= n ; i ++) cin >> a[i];
sort(a + 1, a + n + 1);
for(int i = 1; i <= n ; i ++){
if(a[i] == a[i + 1]) {
cout << "no\n";
return;
}
}
cout << "yes\n";
}
int main(){
cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);
int t;
cin >> t;
while(t-- ) solve();
return 0;
}
B
大意:字符串a是原序列。b是用字符串a两个两个拉长而成的。现在给你字符串b,要求原序列a
思路:
简单分析得知:b序列一定是偶数长度!因为b序列长度是a序列长度的2倍!
只需要将b序列的首尾和中间跳2格的加入ans即可。
AC代码:
#include <bits/stdc++.h>
#define endl '\n'
using namespace std;
void solve(){
string s;
cin >> s;
string ans;
for(int i = 0 ; i <= s.size() - 1; i ++){
if(i != 0 && i != s.size() - 1){
ans += s[i++];
}else{
ans += s[i];
}
}cout << ans << endl;
}
int main(){
cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);
int t;
cin >> t;
while(t--) solve();
return 0;
}
C
大意:
给你数字序列a,问能否通过变换得到字符串
变换规则:相同的数字必须变成一样的字符。变成什么字母是任意的。
思路:检查所有相同数字的对应的字母必须相同即可。
AC代码:
#include <bits/stdc++.h>
#define endl '\n'
using namespace std;
void solve(){
int n;
cin >> n;
vector<int> a(n + 1);
for(int i = 0; i < n ;i ++) cin >> a[i];
string b;
cin >> b;
for(int i = 0; i < n; i ++){ //遍历每一个val
for(int j = i + 1; j < n; j ++){
if(a[i] == a[j] && b[i] != b[j]){
cout << "no\n";
return;
}
}
}
cout << "yes\n";
}
int main(){
cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);
int t;
cin >> t;
while(t--) solve();
return 0;
}
D
大意: 求n个数的两个下标和最大 要求:这两个下标对应val值必须互质
思路:观察到ai的数据范围只有0---1000,因此可以考虑去重。
为了保证下标的最大,因此去重复元素后,保留下来的值对应的下标必须是最大的!
可以用桶来筛,留一个下标最大值。然后再装进数组里,对1000个数据进行O(n²)暴力gcd,满足gcd == 1的就是互质的。
#include <bits/stdc++.h>
#define endl '\n'
using namespace std;
bool tag[1000 + 5];
int sp[1000 + 5];
int a[200005];
int gcd(int a, int b){
if(b) return gcd(b, a % b);
return a;
}
void s(){
int n;
cin >> n;
memset(tag, 0, sizeof tag);
memset(sp, 0, sizeof sp);
for(int i = 1; i <= n ;i++) cin >> a[i];
for(int i = 1; i <= n ; i ++){
tag[a[i]] = 1;
sp[a[i]] = i;
}
vector<int> c;
for(int i = 1; i <= 1000; i ++)
if(tag[i])
c.push_back(i);
int ans = -1;
for(int i = c.size() - 1; i >= 0; i --){
for(int j = i; j >= 0; j --){
if(gcd(c[i], c[j]) == 1) {
ans = max(ans, sp[c[i]] + sp[c[j]]);
}
}
}
cout << ans << endl;
}
int main(){
cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);
int t;
cin >> t;
while(t--) s();
return 0;
}
E
大意:
餐厅价格x序列
每个人兜里有的钱y序列
问这些人两个拼团或者多个拼团,最多能去餐馆几天?
例如
6
8 3 9 2 4 5//餐厅价格
5 3 1 4 5 10//兜里的钱
思路:用yi - xi 从小到大排序,左边是穷人,右边是富人。富人如果能带一个穷人就算赢一天。如果穷人太穷了,那就不要他了,继续往右找不太穷的人组队。
AC代码:
#include <bits/stdc++.h>
#define endl '\n'
using namespace std;
struct node{
int x, y, substract;
}a[200005];
bool cmp(struct node &a, struct node &b){
return a.substract < b.substract;
}
void solve(){
int n;
cin >> n;
for(int i = 1; i <= n; i ++) cin >> a[i].x;
for(int j = 1; j <= n; j ++) cin >> a[j].y;
for(int i = 1; i <= n; i ++) a[i].substract = a[i].y - a[i].x;
sort(a + 1, a + 1 + n, cmp);
int ans = 0;
for(int i = 1, j = n; i < j; i ++){
if(a[i].y + a[j].y >= a[i].x + a[j].x){
ans ++;
j --;
}
}
cout << ans << endl;
}
int main(){
cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);
int t;
cin >> t;
while(t--) solve();
return 0;
}