赛时难度:G>F>E>C>D>B>A
补题难度F>C>G>E>D>B>A
F也是一个模拟题,只是比较的难,我没写出来。。。
这场打的莫名奇妙,主要是被C卡了,C这个玄学题
题意:一支球队在一个赛季有n场足球赛,每场足球赛有三种结果。赢:得w分;平局:得d分;输:不得分。已知最后这支球队得了p分,但是不知道这支球队胜负平的情况,让你求一组可行解。
扩展欧几里得做法,我不太会:参考博客
做法1:
#include <iostream>
#include <queue>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
void exgcd(LL a, LL b, LL& x, LL& y, LL& c) {
if(!b) {y = 0; x = 1; c = a; return;}
exgcd(b,a%b,y,x,c); y -= a/b*x;
}
int main() {
LL n,p,w,d;
cin >> n >> p >> w >> d;
// wx+dy = gcd w,d
LL x,y,c;
exgcd(w,d,x,y,c);
LL v1 = p/w,v2 = 0,m = p%w;
v2 = m/d; m = m%d;
//cout << x << " " <<y<<"\n";
if (m%c == 0) {
LL t = m/c;
v1 += t*x;
v2 += t*y;
LL t1 = w/c,t2 = d/c;
// +t1 -t2
while (v1 < 0) {
v1 += t2;
v2 -= t1;
if (v2 < 0) {
puts("-1");
return 0;
}
}
while (v2 < 0) {
v1 -= t2;
v2 += t1;
if (v1 < 0) {
puts("-1");
return 0;
}
}
while (n-v1-v2 < 0) {
if (t1 > t2) {
v1 += t2;
v2 -= t1;
if (v2 < 0) {
puts("-1");
return 0;
}
} else if (t1 < t2) {
v1 -= t2;
v2 += t1;
if (v1 < 0) {
puts("-1");
return 0;
}
} else {
puts("-1");
return 0;
}
}
if (v1>=0 && v2>=0 && n-v1-v2>=0) {
cout << v1 << " " << v2 << " " << n-v1-v2 << "\n";
return 0;
}
}
puts("-1");
return 0;
}
做法2:参考博客
题解:暴力即可。枚举平局场数,可以将平局局数限制在 w - 1。因为对于同样的分数 w * d,可以赢d场,可以平w场,但是题目保证d严格小于w,所以赢d场肯定最优。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
ll n, p, d, w;
cin>>n>>p>>w>>d;
for(ll i = 0; i <= n && i <= 100000; ++i){
ll tmp = p - i * d;
if(tmp >= 0 && tmp % w == 0){
ll t = tmp / w;
if(t + i <= n){
printf("%lld %lld %lld\n", t, i, n - t - i);
return 0;
}
}
}
puts("-1");
}
D. Paint the Tree
题意:给你一颗树,每个点可以染三个颜色中的一个,每个节点染一种颜色有对应的花费。。
现要求相邻的三个点的颜色不能相同,问如何染色使得花费最小
做法:通过简单的观察可以知道,只有一条链的时候才能成功染色,否则输出-1
那么枚举前两个节点的颜色,所有节点的染色情况就可以得到了。
挺水的一题。。。。。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+10;
int du[N];
vector<int>G[N];
int n;
int a[4][N],b[N],c[N];
ll mi,ans;
void dfs(int u,int x,int y,int fa)
{
//printf("u:%d\n",u);
for(int v:G[u])
{
if(v==fa) continue;
b[v]=6-x-y;
ans+=a[b[v]][v];
dfs(v,b[v],x,u);
}
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;++i) scanf("%d",&a[1][i]);
for(int i=1;i<=n;++i) scanf("%d",&a[2][i]);
for(int i=1;i<=n;++i) scanf("%d",&a[3][i]);
bool flag=1;
for(int i=1;i<n;++i)
{
int u,v;
scanf("%d%d",&u,&v);
G[u].push_back(v);
G[v].push_back(u);
du[u]++;
du[v]++;
}
int id=-1;
mi=0x3f3f3f3f3f3f3f3f;
for(int i=1;i<=n;++i) {
if(du[i]>=3) flag=0;
if(du[i]==1) id=i;
}
if(!flag) {
printf("-1\n");
return 0;
}
//printf("****\n");
for(int i=1;i<=3;++i){
for(int j=1;j<=3;++j)
{
if(i==j) continue;
b[id]=i;
b[G[id][0]]=j;
ans=a[i][id];
ans+=a[j][G[id][0]];
dfs(G[id][0],j,i,id);
//printf("aid:%d ag:%d\n",a[i][id],a[j][G[id][0]]);
if(ans<mi)
{
mi=ans;
for(int k=1;k<=n;++k) c[k]=b[k];
}
mi=min(ans,mi);
}
}
printf("%lld\n",mi);
for(int i=1;i<=n;++i) printf("%d ",c[i]);
}
E. Minimizing Difference
题意:给你一个数组a[i]和一个k,每次可以选择一个值,要么将其增一,要么减一。问最多执行k次操作,问最后的序列中最大值减最小值的答案最小是多少?
做法:将数组排序去重,然后判断左端点和右端点的数量小的一端进行操作即可。。
也挺水,可惜没机会看这题。。。
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
typedef long long ll;
int a[N];
ll k;
map<int,int>vis;
int n;
int main()
{
cin>>n>>k;
for(int i=1;i<=n;++i) {
scanf("%d",&a[i]);
vis[a[i]]++;
}
sort(a+1,a+1+n);
n=unique(a+1,a+1+n)-a-1;
int l=1,r=n;
int mi=a[1],mx=a[n];
//printf("n:%d\n",n);
while(l<r)
{
//printf("vis[l]:%d vis[r]:%d\n",vis[a[l]],vis[a[r]]);
if(vis[a[l]]<vis[a[r]]){
ll d=a[l+1]-a[l];
d=d*vis[a[l]];
if(k>=d)
{
k-=d;
vis[a[l+1]]+=vis[a[l]];
mi=a[l+1];
}
else{
ll t=k/vis[a[l]];
mi=a[l]+t;
k-=t*vis[a[l]];
break;
}
++l;
}
else{
ll d=a[r]-a[r-1];
d=d*vis[a[r]];
//printf("d:%lld\n",d);
if(k>=d){
k-=d;
vis[a[r-1]]+=vis[a[r]];
mx=a[r-1];
}
else{
ll t=k/vis[a[r]];
k-=t*vis[a[r]];
mx=a[r]-t;
break;
}
--r;
}
//printf("l:%d r:%d k:%lld\n",l,r,k);
}
//printf("l:%d r:%d mx:%d mi:%d k:%lld\n",l,r,mx,mi,k);
//printf("vr:%d vl:%d\n",vis[a[r]],vis[a[l]]);
printf("%d\n",mx-mi);
}
G. Running in Pairs
题意:题意比较难懂,主要是有两个跑道,每个跑道有n个人,每个人的奔跑时间是1~n的排列,
第一对人开始跑,每个跑道只能一个人,那么这次的时间消费等于最慢的人时间。。
现给你一个k,问你如何分配两个跑道的人,使得时间消耗最大且不超过k。。
做法:
参考来自:javascript:void(0)
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
typedef long long ll;
int n;
ll k;
int a[N],b[N];
int main()
{
cin>>n>>k;
if(k<1ll*n*(n+1)/2){
printf("-1");
return 0;
}
for(int i=1;i<=n;++i)a[i]=b[i]=i;
int l=1;
ll sum=1ll*n*(n+1)/2;
//printf("sum:%lld\n",sum);
for(int i=n;i>=1&&i>l;--i)
{
ll t=i-l;
//printf("i:%d t:%lld\n",i,t);
if(sum+t<=k&&sum+t>sum) {
swap(a[i],a[l]);
++l,sum=sum+t;
}
}
printf("%lld\n",sum);
for(int i=1;i<=n;++i) printf("%d ",a[i]);
puts("");
for(int i=1;i<=n;++i) printf("%d ",b[i]);
}