Codeforces Round 896 (Div. 2) A-D2

发布时间 2023-09-11 15:28:35作者: xx019

A. Make It Zero

没看懂这个 8 次的限制是什么意思。先用一次直接把所有数变成 \(\oplus_{i=1}^n a_i\),如果 \(n\) 是偶数直接 \([1,n]\) 做完,如果是奇数先把 \([1,n-1]\) 变成 0,再做两遍 \([n-1,n]\) 即可。

点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int inf=1e18;
inline int read(){
	int x=0,f=1;char ch=getchar();
	while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
	while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
	return x*f;
}
int a[100005];
void solve(){
	int n=read();
	for(int i=1;i<=n;i++)a[i]=read();
	if(n%2==0){
		printf("2\n1 %lld\n1 %lld\n",n,n);
	} 
	else{
		printf("4\n1 %lld\n1 %lld\n%lld %lld\n%lld %lld\n",n,n-1,n-1,n,n-1,n);
	}
}
signed main(){
	int T=read();
	while(T--)solve(); 
	return 0;
}

B. 2D Traveling

\(a\to b\) 的最短路只有两种可能:\(a\) 直接到 \(b\)\(a,b\) 到主要城市的最短路之和。

点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int inf=1e18;
inline int read(){
	int x=0,f=1;char ch=getchar();
	while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
	while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
	return x*f;
}
int n,k,a,b,x[200005],y[200005];
int dist(int i,int j){
	if(i<=k&&j<=k)return 0;
	return abs(x[i]-x[j])+abs(y[i]-y[j]);
}
void solve(){
	n=read(),k=read(),a=read(),b=read();
	for(int i=1;i<=n;i++)x[i]=read(),y[i]=read();
	int ans=dist(a,b),da=inf,db=inf;
	for(int i=1;i<=k;i++)da=min(da,dist(a,i));
	for(int i=1;i<=k;i++)db=min(db,dist(b,i));
	ans=min(ans,da+db);
	printf("%lld\n",ans);
}
signed main(){
	int T=read();
	while(T--)solve(); 
	return 0;
}

C. Fill in the Matrix

\(n\ge m-1\) 时,答案就是 \(m\);反之,答案是 \(n+1\)。最大值显然,给一个构造:当 \(n=m-1\) 时,令 \(a_{i,j}=(i+j)\bmod m,i\in[0,n),j\in[0,m)\) 即可。如果 \(n>m-1\) 就复制最后一行,如果 \(n<m-1\) 就把 \(m\) 当成 \(n+1\),每一行后面随便填。

特判一下 \(m=1\)\(n=1\)

点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int inf=1e18;
inline int read(){
	int x=0,f=1;char ch=getchar();
	while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
	while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
	return x*f;
}
void solve(){
	int n=read(),m=read();
	if(n==1&&m==1){
		printf("0\n");
		for(int i=0;i<n;i++){
			for(int j=0;j<m;j++){
				printf("0 ");
			}
			puts("");
		}
		return;
	}
	if(m==1){
		printf("0\n");
		for(int i=0;i<n;i++){
			for(int j=0;j<m;j++){
				printf("0 ");
			}
			puts("");
		}
		return;
	}
	if(n==1){
		printf("2\n");
		for(int i=0;i<n;i++){
			for(int j=0;j<m;j++){
				printf("%lld ",j);
			}
			puts("");
		}
		return;
	}
	if(n>=m-1){
		printf("%lld\n",m);
		for(int i=0;i<m-1;i++){
			for(int j=0;j<m;j++){
				printf("%lld ",(i+j)%m);
			}
			puts("");
		}
		for(int i=m-1;i<n;i++){
			for(int j=0;j<m;j++){
				printf("%lld ",(m-2+j)%m);
			}
			puts("");			
		}
		return;
	}
	else{
		int M=n+1;printf("%lld\n",M);
		for(int i=0;i<n;i++){
			for(int j=0;j<M;j++){
				printf("%lld ",(i+j)%M);
			}
			for(int j=M;j<m;j++){
				printf("%lld ",j);
			}
			puts("");
		}
		return;		
	}
}
signed main(){
	int T=read();
	while(T--)solve(); 
	return 0;
}

D1. Candy Party (Easy Version)

首先平均数不是整数不行,每个数与平均数的差不能写成 \(2^x-2^y\) 的形式不行。然后我们开个桶看一下每一位是不是一样多。

点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int inf=1e18;
inline int read(){
	int x=0,f=1;char ch=getchar();
	while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
	while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
	return x*f;
}
int a[200005],cnt[1005];
void solve(){
	for(int i=0;i<=100;i++)cnt[i]=0;
	int n=read(),s=0;
	for(int i=1;i<=n;i++)a[i]=read(),s+=a[i];
	if(s%n)return puts("No"),void();
	s/=n;
	for(int i=1;i<=n;i++){
		if(s>=a[i]){
			int o=s-a[i],p1=0,p2=0;
			while(o&&o%2==0)o/=2,p1++;
			p2=p1;while(o&&o%2==1)o/=2,p2++;
			if(o)return puts("No"),void();
			cnt[p1]++,cnt[p2]--;
		}
		else{
			int o=a[i]-s,p1=0,p2=0;
			while(o&&o%2==0)o/=2,p1++;
			p2=p1;while(o&&o%2==1)o/=2,p2++;
			if(o)return puts("No"),void();	
			cnt[p1]--,cnt[p2]++;
		}
	}
	for(int i=0;i<=100;i++)if(cnt[i]!=0)return puts("No"),void();
	puts("Yes");
}
signed main(){
	int T=read();
	while(T--)solve(); 
	return 0;
}

D2. Candy Party (Hard Version)

考试的时候蠢了。这个题在上一个题的基础上多了一种选择:当差可以表示成 \(2^x\) 时,我们既可以当成 \(2^x\) 也可以当成 \(2^{x+1}-2^x\)。那我们先统计那些只有一种选择的数的影响,再考虑这些有两种选择的数该怎么选。因为一个 \(|a_i-\text{average}|=2^i\) 选择表示为 \(2^{i+1}-2^i\),那么它会影响 \(i,i+1\) 位,否则只会影响 \(i\) 位。所以我们从高到低决定就行了。

点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int inf=1e18;
inline int read(){
	int x=0,f=1;char ch=getchar();
	while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
	while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
	return x*f;
}
int a[200005],cnt[1005],v[2][1005];
void solve(){
	for(int i=0;i<=100;i++)cnt[i]=v[0][i]=v[1][i]=0;
	int n=read(),s=0;
	for(int i=1;i<=n;i++)a[i]=read(),s+=a[i];
	if(s%n)return puts("No"),void();
	s/=n;
	for(int i=1;i<=n;i++){
		if(s>a[i]){
			int o=s-a[i],p1=0,p2=0;
			while(o&&o%2==0)o/=2,p1++;
			p2=p1;while(o&&o%2==1)o/=2,p2++;
			if(o)return puts("No"),void();
			if(p2!=p1+1)cnt[p1]++,cnt[p2]--;
			else v[1][p1]++;
		}
		else if(s<a[i]){
			int o=a[i]-s,p1=0,p2=0;
			while(o&&o%2==0)o/=2,p1++;
			p2=p1;while(o&&o%2==1)o/=2,p2++;
			if(o)return puts("No"),void();	
			if(p2!=p1+1)cnt[p1]--,cnt[p2]++;
			else v[0][p1]++;
		}
	}
	for(int i=100;i>=1;i--){
		int val=cnt[i]+(v[0][i]-v[1][i]);
		if(val>0){
			if(v[1][i-1]<val)return puts("No"),void();
			v[1][i-1]-=val,cnt[i-1]+=val;
		}
		else if(val<0){
			if(v[0][i-1]<-val)return puts("No"),void();
			v[0][i-1]-=-val,cnt[i-1]-=-val;
		}
	}
	if(cnt[0]+(v[0][0]-v[1][0])==0)puts("Yes");
	else puts("No");
}
signed main(){
	int T=read();
	while(T--)solve(); 
	return 0;
}