2024-08-27-ABC368
A - Cut
给定数组,将右边k个数挪到左边并输出。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int n,a[105],k;
int main()
{
cin>>n>>k;
for(int i=0;i<n;i++)
cin>>a[i];
for(int i=n-k,j=0;j<n;j++,i=(i+1)%n)
cout<<a[i]<<" ";
return 0;
}
B - Decrease 2 max elements
给定一个数组,每次将最大的两个数减一,直到只有一个或无正数。输出操作的次数。
模拟即可
#include <bits/stdc++.h>
#define ll long long
using namespace std;
ll n,a[105];
int main(){
ll i,ans=0;
cin>>n;
for(i=0;i<n;i++)
{
cin>>a[i];
}
while(true)
{
sort(a,a+n);
if(a[n-2]<=0)
{
break;
}
ans++;
a[n-1]--,a[n-2]--;
}
cout<<ans<<'\n';
return 0;
}
C - Triple Attack
有n个怪物,依次打他们,每个时刻会攻击一次,造成一点伤害,每攻击两次后的第三次攻击就可以打出三点伤害(即1,1,3,1,1,3这样循环),问打死所有怪物的时刻。
模拟,对于每个怪,我们先把打上个怪没打完的循环打掉,然后用剩下的血量对5取模,看还要打多少个循环,再处理一下剩下的血量即可。
#include <bits/stdc++.h>
#define ll long long
using namespace std;
ll n,a[200005],t=0;
int main(){
ll i;
scanf("%lld",&n);
for(i=0;i<n;i++)
{
scanf("%lld",&a[i]);
while(t%3!=0&&a[i]>0)
{
t++;
a[i]-=(t%3==0?3:1);
}
if(a[i]<=0)
{
continue;
}
t+=(a[i]/5)*3;
a[i]%=5;
while(a[i]>0)
{
t++;
a[i]-=(t%3==0?3:1);
}
}
printf("%lld\n",t);
return 0;
}
D - Minimum Steiner Tree
给定一棵树,问保留k个指定顶点后,联通的最小顶点数是多少。
以某一个保留的点为根进行的dfs,对于每一个点,如果子树里有保留的点,那么当前点也一定需要保留,算一遍就好了。
#include <bits/stdc++.h>
#define ll long long
#define N 200010
using namespace std;
ll n,k,sz[N];
vector<ll> vt[N];
void dfs(ll x,ll lst)
{
ll i;
for(i=0;i<vt[x].size();i++)
{
if(vt[x][i]!=lst)
{
dfs(vt[x][i],x);
sz[x]+=sz[vt[x][i]];
}
}
return;
}
int main(){
ll i,x,y;
scanf("%lld%lld",&n,&k);
for(i=1;i<n;i++)
{
scanf("%lld%lld",&x,&y);
x--,y--;
vt[x].push_back(y);
vt[y].push_back(x);
}
while(k--)
{
scanf("%lld",&x);
x--;
sz[x]=1;
}
dfs(x,-1);
ll ans=0;
for(i=0;i<n;i++)
{
ans+=(sz[i]>0);
}
printf("%lld\n",ans);
return 0;
}
E - Train Delay
这道题比G题通过的人数还少。
给定n条火车线路,每一条火车线路给定起点、终点、发车时间、到达时间。
现在已知第一条火车线路会延误x1分钟,请问剩下来所有线路的延误时间,使本来能在一个地方换乘的火车,之后也能换乘(即两辆火车一个到达早于另一辆发车,在延误后依然是到达早于发车)
首先这题肯定是个贪心,我们对于每一列火车都让其能尽量早发车就行。
我们按照时间顺序去处理每一辆火车的出发和到达,因为题目限制,延误后的没一辆火车的出发到达顺序应该都是不变的,并且维护一个数组,用于记录每个站点的火车的最晚到站时间tm[]。
遇到一个火车的出发时(设是从x出发),我们可以根据这个数组计算出这个火车出发所需要的延误时间,即tm[x]-s,就是刚好这个站之前的火车到达后出发。
遇到一个火车的到达时,就去更新一下我们的tm数组即可。
这题不难,不知道为什么人少。
#include <bits/stdc++.h>
using namespace std;
int main()
{
int N, M, X0;
cin >> N >> M >> X0;
vector<int> A(M), B(M), S(M), T(M);
for (int i = 0; i < M; i++) {
cin >> A[i] >> B[i] >> S[i] >> T[i];
A[i]--;
B[i]--;
}
vector<array<int, 3> > e(2 * M);
for (int i = 0; i < M; i++) {
e[2 * i] = {S[i], 1, i};
e[2 * i + 1] = {T[i], 0, i};
}
sort(e.begin(), e.end());
vector<int> X(M);
vector<int> tm(N);
X[0] = X0;
for (auto [t, o, i] : e) {
if (o == 1) {
X[i] = max(X[i], tm[A[i]] - S[i]);
} else {
tm[B[i]] = max(tm[B[i]], T[i] + X[i]);
}
}
for (int i = 1; i < M; i++) {
cout << X[i] << " \n"[i == M - 1];
}
return 0;
}
F - Dividing Game
给定n个数,两个人玩游戏,每一轮选一个数,将其变成这个数的真因子,无法操作就输了,问谁赢。
经典取石子,对于每一个数,把这个数操作到1的操作次数为这个数的质因子数量(可以理解为把这个数质因数分解,然后每次可以拿走任意数量的质因子),那么就是有n堆石子,谁取完就赢,和取石子游戏一模一样了,结果就是每一堆的石子数量相互异或,最后异或和为0先手必败,否则先手必胜。
#include <bits/stdc++.h>
using namespace std;
int n,ans;
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin>>n;
for(int i=0;i<n;i++){
int x,sg=0;
cin>>x;
for(int j=2;j<=sqrt(x);j++)
{
while(x%j==0){
x/=j;
sg++;
}
}
if(x!=1) sg++;
ans^=sg;
}
if(ans) cout<<"Anna";
else cout<<"Bruno";
return 0;
}