USACO 12月 2022-2023 December Contest Silver银组 题解

版权声明:本文为CSDN博主「GeekAlice」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

目录

Problem 1. Barn Tree

Problem 2. Circular Barn

Problem 3. Range Reconstruction


Problem 1. Barn Tree

Farmer John's farm has NN barns (2≤N≤2⋅1052≤N≤2⋅105) numbered 1…N1…N. There are N−1N−1 roads, where each road connects two barns and it is possible to get from any barn to any other barn via some sequence of roads. Currently, the jjth barn has hjhj hay bales (1≤hj≤1091≤hj≤109).

To please his cows, Farmer John would like to move the hay such that each barn has an equal number of bales. He can select any pair of barns connected by a road and order his farmhands to move any positive integer number of bales less than or equal to the number of bales currently at the first barn from the first barn to the second.

Please determine a sequence of orders Farmer John can issue to complete the task in the minimum possible number of orders. It is guaranteed that a sequence of orders exists.

INPUT FORMAT (input arrives from the terminal / stdin):

The first line of input contains the value of N.N.

The second line of input contains the space-separated values of hjhj for j=1…Nj=1…N.

The final N−1N−1 lines of input each contain two space-separated barn numbers ui viui vi, indicating that there is a bidirectional road connecting uiui and vivi.

OUTPUT FORMAT (print output to the terminal / stdout):

Output the minimum possible number of orders, followed a sequence of orders of that length, one per line.

Each order should be formatted as three space-separated positive integers: the source barn, the destination barn, and the third describes the number of hay bales to move from the source to the destination.

If there are multiple solutions, output any.

SAMPLE INPUT:

4
2 1 4 5
1 2
2 3
2 4

SAMPLE OUTPUT:

3
3 2 1
4 2 2
2 1 1

In this example, there are a total of twelve hay bales and four barns, meaning each barn must have three hay bales at the end. The sequence of orders in the sample output can be verbally translated as below:

  1. From barn 33 to barn 22, move 11 bale.
  2. From barn 44 to barn 22, move 22 bales.
  3. From barn 22 to barn 11, move 11 bale.

SCORING:

  • Test cases 2-8 satisfy N≤5000N≤5000
  • Test cases 7-10 satisfy vi=ui+1vi=ui+1
  • Test cases 11-16 satisfy no additional constraints

#include<bits/stdc++.h>
using namespace std;          
#define mpp(a,b,c) make_pair(a,make_pair(b,c))
#define _1 first
#define _2 second.first
#define _3 second.second   
#define pb push_back 
#define eb emplace_back  
#define int long long
namespace IO{
    inline int read(){
    	int ans=0,flag=1;
    	char ch=getchar();
    	while(!isdigit(ch)){
    	    if(ch=='-')flag=-1;  
    	    ch=getchar();
    	}
    	while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
    	return ans*flag;
    }
    inline string reads(){
    	string ans="";char ch=getchar();
    	while(ch==' '||ch=='\n')
    	    ch=getchar();
    	while(ch!=' '&&ch!='\n')
    	    ans+=ch,ch=getchar();  
    	return ans;
    }
    inline char readc(){
    	char ch=getchar();
    	while(ch==' '||ch=='\n')
    	    ch=getchar();
    	return ch;
    }
    inline int sqr(int x){
        return x*x;
    }
    inline void reada(int *a,int len){
        for(int i=1;i<=len;i++)
        a[i]=read();
    }  
    void write(int x){
    	if(x<0)putchar('-'),x=-x;
    	if(x>9)write(x/10);
    	putchar(x%10+'0');
    	return;
    }
}
using IO::read;
const int N=4e5+7; 
bool mem1=0,mem2=0;
int Datas=0,T=1,n,avg=0,h[N];  
vector<int>g[N]; 
long long ned[N];  
vector<pair<int,pair<int,long long> > >opt;
void solve(int u,int fa){
	for(auto v:g[u]){
		if(v==fa||ned[v]<=0)continue;
		opt.eb(mpp(u,v,ned[v]));
		solve(v,u); 
	}
}
void dfs(int u,int fa){ 
	for(auto v:g[u]){
	    if(v==fa)
	    continue;
	    dfs(v,u); 
	}
	for(auto v:g[u]){
	    if(v==fa)continue;
	    ned[u]+=ned[v];
	}
	ned[u]+=avg-h[u];
	if(ned[u]<=0){
	    solve(u,fa);
	    if(ned[u]!=0) 
	    opt.eb(mpp(u,fa,-ned[u]));
	}
}
void Main(){
	n=read();
	long long sum=0;
	for(int i=1;i<=n;i++)h[i]=read(),sum+=h[i];
	avg=sum/n;
	for(int i=1;i<n;i++){
		int u=read(),v=read(); 
		g[u].pb(v),g[v].pb(u);
	}dfs(1,0);
	printf("%lld\n",(int)(opt.size()));
	for(auto x:opt){
		printf("%lld %lld %lld\n",x._1,x._2,x._3);
	}
	return;
} 
signed main(){
#ifdef EXODUS
	printf("%.5lfMB\n",abs(&mem2-&mem1)/1024.0/1024.0);
	freopen("Data.in","r",stdin);
	freopen("Code.out","w",stdout); 
#endif
#ifdef online_judge
	freopen("input.in","r",stdin);
	freopen("user_out.out","w",stdout); 
#endif
	if(Datas)T=read();
	while(T--)Main();
#ifdef EXODUS
	cerr<<clock()<<"ms"<<endl; 
#endif
	return 0; 
} 

Problem 2. Circular Barn

Farmer John and his archnemesis Farmer Nhoj are playing a game in a circular barn. There are NN (1≤N≤1051≤N≤105) rooms in the barn, and the iith room initially contains aiai cows (1≤ai≤5⋅1061≤ai≤5⋅106). The game is played as follows:

  • Both farmers will always be in the same room. After entering a room, each farmer takes exactly one turn, with Farmer John going first. Both farmers initially enter room 11.
  • If there are zero cows in the current room, then the farmer to go loses. Otherwise, the farmer to go chooses an integer PP, where PP must either be 11 or a prime number at most the number of cows in the current room, and removes PP cows from the current room.
  • After both farmers have taken turns, both farmers move to the next room in the circular barn. That is, if the farmers are in room ii, then they move to room i+1i+1, unless they are in room NN, in which case they move to room 11.

Determine the farmer that wins the game if both farmers play optimally.

INPUT FORMAT (input arrives from the terminal / stdin):

The input contains TT test cases. The first line contains TT (1≤T≤10001≤T≤1000). Each of the TT test cases follow.

Each test case starts with a line containing NN, followed by a line containing a1,…,aNa1,…,aN.

It is guaranteed that the sum of all NN is at most 2⋅1052⋅105.

OUTPUT FORMAT (print output to the terminal / stdout):

For each test case, output the farmer that wins the game, either "Farmer John" or "Farmer Nhoj."

SAMPLE INPUT:

5
1
4
1
9
2
2 3
2
7 10
3
4 9 4

SAMPLE OUTPUT:

Farmer Nhoj
Farmer John
Farmer John
Farmer John
Farmer Nhoj

For the first test case, Farmer John can remove 11, 22, or 33 cows from the first room. Whichever number he removes, Nhoj can remove the remaining cow(s), forcing FJ to lose when they circle back to the first room.

For the second test case, FJ can remove 55 cows, forcing Nhoj to work with only 44 cows remaining. Now, Nhoj can either remove 11, 22, or 33 cows. This is now similar to the first test case.

For the third and fourth test cases, FJ can immediately remove all the cows from the first room, forcing Nhoj to lose.

For the fifth test case, FJ can remove 11, 22, or 33, cows from the first room, and Nhoj can remove the rest right after. When they circle back around to the first room, FJ will lose.

SCORING:

  • Inputs 2-4 satisfy N=1N=1.
  • Inputs 1, 2, and 5-7 satisfy ai≤1000ai≤1000.
  • Inputs 8-20 satisfy no additional constraints.
#include<bits/stdc++.h>
using namespace std;  
#define il inline   
#define np pair<int,int> 
#define mp(a,b) make_pair(a,b)     
namespace IO{
    il int read(){
    	int ans=0,flag=1;
    	char ch=getchar();
    	while(!isdigit(ch)){if(ch=='-')flag=-1;ch=getchar();}
    	while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
    	return ans*flag;
    }
    il string reads(){
    	string ans="";char ch=getchar();
    	while(ch==' '||ch=='\n')ch=getchar();
    	while(ch!=' '&&ch!='\n')ans+=ch,ch=getchar();
    	return ans;
    }
    il char readc(){
    	char ch=getchar();
    	while(ch==' '||ch=='\n')ch=getchar();
    	return ch;
    }
    il int sqr(int x){return x*x;}
    il void reada(int *a,int len){for(int i=1;i<=len;i++)a[i]=read();}
    void write(int x){
    	if(x<0)putchar('-'),x=-x;
    	if(x>9)write(x/10);
    	putchar(x%10+'0');
    	return;
    }
}
using IO::read;
bool mem1=0;
int Datas=1,T=1;
const int N=5e6+7,P=5e6+7;
int pri[P],cnt=0,n,a[N];
bool chk[N]; 
void get_prime(int Up){
	chk[1]=0;pri[++cnt]=1;
	for(int i=2;i<=Up;i++){
		if(!chk[i])pri[++cnt]=i;
		for(int j=2;j<=cnt&&pri[j]*i<=Up;j++){
		    chk[i*pri[j]]=1;
		    if(i%pri[j]==0)
		    break;
		}
	}
} 
int res[N];
bool mem2=0;
void Main(){
	n=read();
	for(int i=1;i<=n;i++){
		a[i]=read();
	}
	np tim1=mp(2e9,2e9),tim2=mp(2e9,2e9);
	for(int i=1;i<=n;i++){
		if(a[i]%4==0){
			tim1=min(tim1,mp(a[i]/2/2+1,i));
		}else{
			if(a[i]&1^1)tim2=min(tim2,mp((a[i]/2+1)/2,i));
			 else{ 
				if(res[a[i]])tim2=min(tim2,mp((res[a[i]]+1)/2,i));
				else{
					for(int j=0;j<=a[i];j+=4){
						if(!chk[a[i]-j]){
							res[a[i]]=j/2+1; 
							break; 
						}
					}
					tim2=min(tim2,mp((res[a[i]]+1)/2,i));
				}
			}
		}
	}
	if(tim1<tim2)puts("Farmer Nhoj");
	else puts("Farmer John");
	return;
} 
int main(){
	get_prime(5e6);
#ifdef EXODUS
	printf("%.5lfMB\n",abs(&mem2-&mem1)/1024.0/1024.0);
	freopen("Data.in","r",stdin);
	freopen("Code.out","w",stdout);
#endif
#ifdef online_judge
	freopen("input.in","r",stdin);
	freopen("user_out.out","w",stdout);
#endif
	if(Datas)T=read();
	while(T--)Main();
#ifdef EXODUS
	cerr<<clock()<<"ms"<<endl;
#endif
	return 0;
} 

 

Problem 3. Range Reconstruction

Bessie has an array a1,…,aNa1,…,aN, where 1≤N≤3001≤N≤300 and 0≤ai≤1090≤ai≤109 for all ii. She won't tell you aa itself, but she will tell you the range of each subarray of aa. That is, for each pair of indices i≤ji≤j, Bessie tells you ri,j=maxa[i…j]−mina[i…j]ri,j=maxa[i…j]−mina[i…j]. Given these values of rr, please construct an array that could have been Bessie's original array. The values in your array should be in the range [−109,109][−109,109].

INPUT FORMAT (input arrives from the terminal / stdin):

The first line contains NN.

Another NN lines follow. The iith of these lines contains the integers ri,i,ri,i+1,…,ri,Nri,i,ri,i+1,…,ri,N.

It is guaranteed that there is some array aa with values in the range [0,109][0,109] such that for all i≤ji≤j, ri,j=maxa[i…j]−mina[i…j]ri,j=maxa[i…j]−mina[i…j].

OUTPUT FORMAT (print output to the terminal / stdout):

Output one line containing NN integers b1,b2,…,bNb1,b2,…,bN in the range [−109,109][−109,109] representing your array. They must satisfy ri,j=maxb[i…j]−minb[i…j]ri,j=maxb[i…j]−minb[i…j] for all i≤ji≤j.

SAMPLE INPUT:

3
0 2 2
0 1
0

SAMPLE OUTPUT:

1 3 2

For example, r1,3=maxa[1…3]−mina[1…3]=3−1=2r1,3=maxa[1…3]−mina[1…3]=3−1=2.

SAMPLE INPUT:

3
0 1 1
0 0
0

SAMPLE OUTPUT:

0 1 1

This example satisfies the constraints for subtask 1.

SAMPLE INPUT:

4
0 1 2 2
0 1 1
0 1
0

SAMPLE OUTPUT:

1 2 3 2

This example satisfies the constraints for subtask 2.

SAMPLE INPUT:

4
0 1 1 2
0 0 2
0 2
0

SAMPLE OUTPUT:

1 2 2 0

SCORING:

  • Test 5 satisfies r1,N≤1r1,N≤1.
  • Tests 6-8 satisfy ri,i+1=1ri,i+1=1 for all 1≤i<N1≤i<N.
  • Tests 9-14 satisfy no additional constraints.
#include<bits/stdc++.h>
using namespace std; 
const int inf=0x3f3f3f3f;
const int Maxn=310;
int n,a[Maxn][Maxn],ans[Maxn],minn[Maxn],maxn[Maxn];
bool vis[Maxn];
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++)for(int j=i;j<=n;j++) scanf("%d",&a[i][j]); 
	int pos=n;
	ans[pos]=0;
	int minn=0,maxx=0;
	memset(vis,-1,sizeof(vis));
	pos--;
	while(pos!=0){
		int ans1=ans[pos+1]+a[pos][pos+1],ans2=ans[pos+1]-a[pos][pos+1]; 
		int minn1=ans1,maxn1=ans1;
		int minn2=ans2,maxn2=ans2; 
		bool flag1=1,flag2=1;
		for(int i=pos+1;i<=n;i++)
		{
			minn1=min(minn1,ans[i]);minn2=min(minn2,ans[i]);
			maxn1=max(maxn1,ans[i]);maxn2=max(maxn2,ans[i]);
			if(maxn2-minn2!=a[pos][i]) flag2=0;  
			if(maxn1-minn1!=a[pos][i]) flag1=0; 
		}
		if(!flag1 && !flag2)
		{  
			pos++;
			vis[pos]=-1;
			continue;
		}
		if(flag1 && !flag2)
		{
			ans[pos]=ans1;
			pos--;
		}else if(flag2 && !flag1){
			ans[pos]=ans2;
			pos--;
		}else if(flag1 && flag2){
			if(vis[pos]==-1)
			{
				ans[pos]=ans1;
				vis[pos]=1;
				pos--;
			}else{
				ans[pos]=ans2;
				vis[pos]=2;
				pos--;
			}
		}
	}
	int awa=inf;
	for(int i=1;i<=n;i++)awa=min(awa,ans[i]); 
	for(int i=1;i<n;i++)printf("%d ",ans[i]-awa); 
	printf("%d\n",ans[n]-awa);
	return 0;
}

USACO2022金组是国际在线判题系统USACO的最高级别,题目难度较高,在该比赛中取得好成绩是一项巨大的成就。以下是对该比赛的一些题目解析。 第一题:“交通计划” 题目要求:给定一个n个节点的有向图,每条边有一个长度,希望添加最少的边使得所有节点连通,求最小生成树的权值和。 解析:该题可以使用Kruskal算法求解,将每条边按权值从小到大排序,再依次加入,判断加入的边是否会形成环,若形成则不加入,直到所有节点连通为止。此时Kruskal算法得到的最小生成树的权值和即为所求。 第二题:“点火计划” 题目要求:给定一个n个节点的有向图,每条边有一个权值和一个点火时长,每个节点有一个点火启动时刻和时刻结束时刻,希望从其中选出一些边点火,使得所有节点都可从点火的边出发到达,且所选点火边的总点火时长最小。 解析:该题可以使用最小费用最大流算法求解。将每条边看做一个容量为1,费用为点火时长的边,源点向节点的点火边容量为1,费用为0的边,节点的点火边向汇点的容量为1,费用为0的边,对这个网络进行最小费用最大流即可得到所选边的总点火时长最小。 第三题:“美味佳肴” 题目要求:给定n个菜品,每个菜品有它的权值和两个类别,希望选出k个菜品,使得选出的菜品数量在每个类别中都不超过$\frac{k}{3}$个,且所选菜品的权值和最大。 解析:该题可以使用动态规划求解。设$f[i][j][k]$表示前i个菜品中,选择j个一类菜品,选择k个二类菜品的最大权值和,状态转移方程为$f[i][j][k]=max(f[i-1][j][k],f[i-1][j-1][k]+a[i],f[i-1][j][k-1]+b[i])$,其中a[i]为i号菜品的权值,若为一类则为该权值,否则为0,b[i]为i号菜品的权值,若为二类则为该权值,否则为0。最终答案为$f[n][$k/3$][$k/3$]。 以上是对USACO2022金组的部分题目的解析,USACO比赛是全球范围内的计算机竞赛,竞争非常激烈,能够在该比赛中脱颖而出是一项非常棒的成就。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值