2024 暑假友谊赛 3
2024.8.3 9:00————12:00
过题数2/8
补题数4/8
- CodeForces 1187E
- CodeForces 977D
- CodeForces 1368D
- AtCoder arc082_b
- CodeForces 794C
- CodeForces 1076E
- CodeForces 611D
- CodeForces 1416B
B - Divide by three, multiply by two
题解:
有一个数字x,现在可以对它进行n-1次操作,既可以是把它除以3(必须是能整除的数字),也可以将它乘上2,现在打乱这些数字,给出打乱后的数字个数n和序列,请输出正确的顺序。
用一个双端队列,先找出最小值,先往左边找过去,能整除以2或能乘上3的数字,找到了就往左边放。然后往右边找,能乘上2或能整除以3的数字,就往右边放,最后输出即可。
代码:
#include<iostream>
#include<queue>
#include<algorithm>
#include<cmath>
#include<utility>
#include<map>
#include<vector>
#include<deque>
using namespace std;
#define int long long
#define endl "\n"
const int N = 110;
int a[N];
int n;
map<int,bool>mp;
signed main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> n;
int mi = 3e18+10;
for (int i = 1; i <= n; i++) {
cin >> a[i];
mp[a[i]]= true;
if(a[i] < mi)mi = a[i];
}
int cnt = 0;
mp[mi] = false;
deque<int>dq;
dq.push_front(mi);
int st = 0;
int res = mi;
while(dq.size() < n) {
bool stt = false;
if(mp[mi*3]) {
dq.push_front(mi*3);
mp[mi*3] = false;
mi = mi*3;
st = 3;
stt = true;
}
// if(mp[mi*2]) {
// dq.push_back(mi*2);
// mp[mi*2] = false;
// mi = mi*2;
// st = 2;
// stt = true;
// }
// if(mi%3 == 0) {
// if(mp[mi/3]) {
// dq.push_back(mi/3);
// mp[mi/3] = false;
// mi = mi/3;
// st = 33;
// stt = true;
// }}
if(mi % 2 == 0) {
if(mp[mi/2]) {
dq.push_front(mi/2);
mp[mi/2] = false;
mi = mi/2;
st = 22;
stt = true;
}
}
// if(!stt) {
// if(st == 2) mi = mi/2;
// if(st == 3) mi = mi/3;
// if(st == 22) mi = mi*2;
// if(st == 33) mi = mi*3;
// }
if(!stt)break;
}
mi = res;
while(dq.size() < n) {
bool stt = false;
// if(mp[mi*3]) {
// dq.push_front(mi*3);
// mp[mi*3] = false;
// mi = mi*3;
// st = 3;
// stt = true;
// }
if(mp[mi*2]) {
dq.push_back(mi*2);
mp[mi*2] = false;
mi = mi*2;
st = 2;
stt = true;
}
if(mi%3 == 0) {
if(mp[mi/3]) {
dq.push_back(mi/3);
mp[mi/3] = false;
mi = mi/3;
st = 33;
stt = true;
}}
// if(mi % 2 == 0) {
// if(mp[mi/2]) {
// dq.push_front(mi/2);
// mp[mi/2] = false;
// mi = mi/2;
// st = 22;
// stt = true;
// }
// }
// if(!stt) {
// if(st == 2) mi = mi/2;
// if(st == 3) mi = mi/3;
// if(st == 22) mi = mi*2;
// if(st == 33) mi = mi*3;
// }
if(!stt)break;
}
while(!dq.empty()) {
cout << dq.front() << ' ';
dq.pop_front();
}
return 0;
}
D - Derangement
题解:
给出一个长度为n的序列p,序列中有1——n各个数字乱序,每次可以交换俩个相邻的数字,要求最后实现每个数字与位置不相等。
找找找,找到一个数字与序列相等的就记一个res,如果左右俩个数字都相等,它们俩可以相互交换,所以res-1,最后输出res即可。
代码:
#include<iostream>
#include<queue>
#include<algorithm>
#include<cmath>
#include<utility>
#include<map>
#include<vector>
using namespace std;
#define int long long
const int N = 1e5+10;
int n;
int p[N];
signed main() {
cin >> n;
int res = 0;
for (int i = 1; i <= n; i++) {
cin >> p[i];
if(p[i] == i) {
if(p[i-1] == i-1 && i-1 != 0) {
swap(p[i-1],p[i]);
res--;
}
res++;
}
}cout << res << endl;
return 0;
}
E - Naming Company
题解:
给公司命名,Oleg手里有一个名字,希望使公司的名字尽可能的小,Igor的手中有一个名字,希望使公司的名字尽可能的大,从Oleg手中的名字开始,轮流取一个字母,放置在公司名字的某个位置,三串名字的长度相等。
先给俩人手中的字母进行排序,截取出俩个人手中打算放的字母,可以想象当Oleg此时要放置的字母比Lgor大的话,后面的字母全都会比它大,所以要把Oleg要放的最后一个字母尽量往后面放,因为要让越小的字母在越前面。
代码:
#include<iostream>
#include<queue>
#include<algorithm>
#include<cmath>
#include<utility>
#include<map>
#include<vector>
#include<deque>
using namespace std;
#define int long long
#define endl "\n"
const int N = 3e5+10;
char oleg[N],igor[N];
char an[N];
priority_queue<char>ig;
priority_queue<char,vector<char>,greater<char>>o;
string mi,ma;
signed main() {
cin >> mi >> ma;
int n = mi.length();
int m = ma.length();
for (int i = 0; i < mi.length(); i++) {
oleg[i] = mi[i];
}sort(oleg,oleg+n);
for (int i = 0; i < ma.length(); i++) {
igor[i] = ma[i];
}sort(igor,igor+m,greater<char>());
int cnt = 0;
int res = n-1;
for (int i = 0; i < n; i++)an[i] = '?';
int qa1 = 0,qa2 = 0;
int ho1 = (n+1)/2-1,ho2 = n/2-1;
for (int i = 1; i <= n; i++) {
if(i%2 == 1) {
if(oleg[qa1] < igor[qa2]) an[cnt++] = oleg[qa1++];
else an[res--] = oleg[ho1--];
}
else {
if(oleg[qa1] < igor[qa2]) an[cnt++] = igor[qa2++];
else an[res--] = igor[ho2--];
}
}
for (int i = 0; i < n; i++)cout << an[i];
return 0;
}
H - Make Them Equal
题解:
t组数据,每组数据有个序列长度为n的数组a,要求通过选取i,j,x,使a[i]=a[i]-xi,a[j]=a[j]+xi进行少于3*n次操作使得所有数字相等。输出操作次数以及相应的操作,不要求操作次数最少。
把所有的数字都给a[1]即可,无法完全给它的先借一点再给它,最后由1再还给大家。如果所有数字的总和无法整除,那么一定没有办法使所有数字相等,输出-1.
代码:
#include<iostream>
#include<queue>
#include<algorithm>
#include<cmath>
#include<utility>
#include<map>
#include<vector>
#include<deque>
using namespace std;
#define int long long
#define endl "\n"
const int N = 1e4+10;
int t;
int a[N];
struct ty {
int p,q,x;
};
signed main() {
cin >> t;
while(t--) {
int n;
cin >> n;
int sum= 0;
vector<ty>an;
for (int i = 1;i <= n; i++) {
cin >> a[i];
sum += a[i];
}
if(sum % n != 0) {
cout << -1 << endl;
continue;
}
sum/=n;
for (int i = 2; i <= n; i++) {
// int res = a[i]/i;
// a[i] = a[i]%i;
// // cout << i << ' ' << 1 << ' ' << res << endl;
// an.push_back({i,1,res});
if(a[i] % i != 0) {
int t = i-a[i]%i;
a[i] += t;
an.push_back({1,i,t});
}
an.push_back({i,1,a[i]/i});
}
// for (int i = 2; i <= n; i++) {
// if(a[i] > sum) {
// an.push_back({1,i,i-a[i]});
// an.push_back({i,1,1});
// }
// }
for (int i = 2; i <= n; i++) {
// cout << 1 << ' ' << i << ' ' << res << endl;
an.push_back({1,i,sum});
}
cout << an.size() << endl;
for (auto x : an) {
cout << x.p << ' ' << x.q << ' ' << x.x << endl;
}
}
return 0;
}