A - Shuffled Equation
翻译:
你被给予了一个序列A=
。
让
为A的任意排列。
确定是否可能使
思路:
让较小的两个相乘,判断是否与最大的相同。
实现:
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
int main(){
// 关闭输入输出流同步
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
// 不使用科学计数法
// cout<<fixed;
// 中间填保留几位小数,不填默认
// cout.precision();
vector<int> a(3);
for (int& i:a)cin>>i;
sort(a.begin(),a.end());
if (a[0]*a[1]==a[2]){
cout<<"Yes"<<endl;
}else{
cout<<"No"<<endl;
}
}
B - Who is Missing?
翻译:
你被给予了一个长为M的整数序列
。
A中的每个元素介于1与N之间,包括1,N,并且每个元素都不同。
列出所有没出现在A中的1到N按升序排列。
思路:
设置一个访问数组vis,初始化为1。遍历A出现在元素 i 将vis[i]=0。最后遍历vis中为1的值。
实现:
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
int main(){
// 关闭输入输出流同步
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
// 不使用科学计数法
// cout<<fixed;
// 中间填保留几位小数,不填默认
// cout.precision();
int n,m;
cin>>n>>m;
vector<int> a(n+1,1);
for (int i=1,num;i<=m;i++){
cin>>num;
a[num] = 0;
}
int f = 0;
cout<<n-m<<endl;
for (int i=1;i<=n;i++){
if (f) cout<<" ";
if (a[i]){
cout<<i;
f = 1;
}
}
}
C - Bib
翻译:
有 N 个人从 1 到 N 开始标记。
i 号人穿着数字为
的围裙并且盯着
号人。
对于每个i=1,2,...,N,找到穿着围裙 i 的人盯着的人上围裙的数字。
思路:
创建3个数组,围裙 i 所对应的人,i 号人所盯的人,i 号人所穿的围裙。
实现:
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
int main(){
// 关闭输入输出流同步
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
// 不使用科学计数法
// cout<<fixed;
// 中间填保留几位小数,不填默认
// cout.precision();
int n;
cin>>n;
// 围裙 穿的人
vector<int> a(n+1);
// 穿的人 围裙
vector<int> c(n+1);
// 当前的人 看的人
vector<int> b(n+1);
for (int num,i=1;i<=n;i++){
cin>>num;
b[i] = num;
}
for (int num,i=1;i<=n;i++){
cin>>num;
a[num] = i;
c[i] = num;
}
for (int i=1;i<=n;i++){
if (i!=1) cout<<" ";
cout<<c[b[a[i]]];
}
}
D - Doubles
翻译:
这有 N 个筛子。第 i 个筛子有
个面,数字
被写在他们上。当你旋转这个筛子每个面出现的可能性为
。
你从 N 个筛子中选择两个筛子并旋转他们。确定两个筛子出现相同数字的最大可能性,当筛子选择最佳时。
思路:
使用map<int,int>记录每个筛子中各个数字出现的次数。
最后对每个筛子进行两两配对。
实现:
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
int main(){
// 关闭输入输出流同步
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
// 不使用科学计数法
// cout<<fixed;
// 中间填保留几位小数,不填默认
cout.precision(15);
int n;
cin>>n;
vector<int> k(n);
// 记录每个筛子中的各种数字数量
vector<unordered_map<int,int>> cnts(n);
// 最大可能性
double ans = 0;
for (int num,i=0;i<n;i++){
cin>>k[i];
for (int j=0;j<k[i];j++){
cin>>num;
cnts[i][num]++;
}
}
// 筛子两两配对
for (int i=0;i<n;i++){
for (int j=i+1;j<n;j++){
int ki = k[i],kj = k[j];
double cnt = 0;
// 遍历筛子i的每种数字及其数量
for (auto &[x,y]:cnts[i]){
// 筛子j存在数字 x
if (cnts[j].count(x))
cnt += 1.0*y/ki*1.0*cnts[j][x]/kj;
}
ans = max(ans,cnt);
}
}
cout<<ans<<endl;
}
E - Cables and Servers
翻译:
这有N个数字1到N的服务器和M条数字1到M的电缆。
电缆i双向连接服务器
。
执行下列操作一些次数(可能0次),使所有服务器通过电缆相互连接。
- 操作:选择一条电缆并重新连接其尾部到另一个服务器。
找到最小数量的操作数并输出到这个最小操作数的操作序列。
思路:
先找到每个连通块的无用边,而每条无用边都可连接两个连通块,对无用边进行遍历使连通块和为1即可。(并查集)
实现:
#include<bits/stdc++.h>
using namespace std;
const int MX = 2e5+10;
int n,m;
// 并查集,无用边
vector<int> f(MX),sizes(MX),unvail;
// 边
vector<vector<int>> edge(MX,vector<int>(2));
// 找祖宗
int find(int x){
return f[x]==x ? x : f[x] = find(f[x]);
}
// 合并
void merge(int x,int y){
x = find(f[x]);
y = find(f[y]);
if (x==y) return;
if (sizes[x]<sizes[y]) swap(x,y);
f[y] = x;
sizes[x]+=sizes[y];
}
int main(){
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
cin>>n>>m;
for (int i=0;i<=n;i++){
f[i] = i;
sizes[i] = 1;
}
for (int i=1;i<=m;i++){
cin>>edge[i][0]>>edge[i][1];
int x = find(edge[i][0]),
y = find(edge[i][1]);
// 不在同一连通块
if (x!=y){
merge(x,y);
// 在同一连通块,为无用边
}else{
unvail.push_back(i);
}
}
// 记录连通块
unordered_set<int> dsus;
for (int i=1;i<=n;i++){
if (f[i]==i) dsus.insert(i);
}
vector<array<int,3>> ans;
// 连接dsus次连通块
for (int i:unvail){
int x = edge[i][0],
y = edge[i][1];
x = find(f[x]);
int now_dus=-1;
while (!dsus.empty()){
int tmp = *dsus.begin();
dsus.erase(dsus.begin());
// 属于自身的连通块且该连通块与x不在同一连通块上
if (tmp==find(f[tmp]) && x!=find(f[tmp])){
now_dus = tmp;
break;
}
}
// 合并为了一个连通块
if (now_dus==-1) break;
ans.push_back({i,y,now_dus});
// 连接now_dus与x两个连通块
merge(now_dus,x);
// 返回新合并出的连通块
dsus.insert(find(f[x]));
}
cout<<ans.size()<<endl;
for (auto [x,y,z]:ans){
cout<<x<<" "<<y<<" "<<z<<endl;
}
}
有建议可以评论,我会积极改进qwq。