Codeforces Round 896 (Div. 2) A-D2
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;
}