A:As long as I was by her side
题意:连续三个人的高度和是三的倍数,就说这三个人是“挺好的”,一组数据进行排序,要求最多“挺好的”组。
分析:把所有数据预处理,mod 3,按照数量进行排序,小的放后面。
例如最小的是2的高度,按照0 1 2输出,最后再输一次0,再输一次1,然后按照1 1 1,0 0 0 这样输出,如果还有数据的话。
题解:
#include<bits/stdc++.h>
using namespace std;
const int MAX=1e5+10;
typedef long long ll;
vector<int>e[3];
int a[MAX];
void f(int x,int y,int z)
{
deque<int>p;
int m=e[z].size();
for(int i=1;i<=m;i++)
{
p.push_back(e[x].back());
e[x].pop_back();
p.push_back(e[y].back());
e[y].pop_back();
p.push_back(e[z].back());
e[z].pop_back();
}
if(e[x].size())
p.push_back(e[x].back()),e[x].pop_back();
if(e[y].size())
p.push_back(e[y].back()),e[y].pop_back();
while(e[x].size())
p.push_front(e[x].back()),e[x].pop_back();
while(e[y].size())
p.push_back(e[y].back()),e[y].pop_back();
int n=1;
while(!p.empty())
a[n++]=p.front(),p.pop_front();
}
int main()
{
int T;
cin>>T;
while(T--)
{
int n;
scanf("%d",&n);
for(int i=0;i<3;i++)
e[i].clear();
for(int i=1;i<=n;i++)
{
int x;
scanf("%d",&x);
e[x%3].push_back(x);
}
if(e[0].size()<e[1].size()) swap(e[0],e[1]);
if(e[0].size()<e[2].size()) swap(e[0],e[2]);
if(e[1].size()<e[2].size()) swap(e[1],e[2]);
if(e[0].size()>=e[1].size()&&e[1].size()>=e[2].size())
f(0,1,2);
for(int i=1;i<=n;i++)
printf("%d%c",a[i]," \n"[i==n]);
}
return 0;
}
K题:Digital Demonstration
题意:输入一个数n,200000次操作之内能否得到114514,操作是把n分为a和b,要求a+b=n,然后n=a*b,如果不可以输出-1,如果可以输出过程。
分析:n小于4就不可以通过这个操作变大了,输出-1。如果n小于114514,我们可以把n拆分成2和n-2进行变大(不唯一),当大于114514,可以分成n-1和1,进行变小,最后得到114514。
题解:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
int n;
cin >> n;
if(n<=4) cout << "-1" << endl;
else
{
vector<int> a;
while(n<114514)
{
a.push_back(n-2);
a.push_back(2);
n = 2*(n-2);
}
while(n!=114514)
{
a.push_back(n-1);
a.push_back(1);
n = n - 1;
}
cout << a.size()/2 << endl;
for(int i=0;i<a.size();i+=2)
cout << a[i] << " " << a[i+1] << endl;
}
return 0;
}
E题 Different colors of wings
题意:输入n,有n+1个山头,行程D的意思是1≤i<j≤n+1,d[i][j]的和。山头可以排成不同的序列,求最大和最小的行程值。
分析:这个在解释中也给了最大和最小的行程的图,最小行程的图是中间一个结点,每个结点都连接中间结点上。最大行程的图是一条链。
其中最小的行程可以根据公式,写出一个双重循环计算。最大行程得先判断每段路使用的次数,然后排序,相乘得出答案。(不开long long 见祖宗,别问我为啥这样说,问就是卡了30%的点)。
题解:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll b[1010];
ll a[1010];
int main()
{
int t;
cin >> t;
while(t--)
{
int n;
cin >> n;
ll minn=0;
for(int i=1;i<=n;i++)
{
cin >> a[i];
minn += a[i];
}
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)
{
minn += a[i]+a[j];
}
}
int p=0;
for(int i=1;i<=n;i++)
{
if((n+1-i)!=0)
b[++p] = i*(n+1-i);
}
sort(b+1,b+1+n);
sort(a+1,a+1+n);
ll maxx=0;
for(int i=n;i>=1;i--)
{
maxx += a[i]*b[i];
}
cout << minn << " " << maxx << endl;
}
}