D. Genius's Gambit
抽象题意:给定 \(a,b,k\),你需要构造两个二进制数\(x,y\),满足以下条件:
1:\(x,y\)均由\(a\)个\(0\)和\(b\)个\(1\)构成
2:\(x-y\)的值用二进制表示只含\(k\)个\(1\)
不允许前导零存在
这个就是个找规律,然后构造。对于\(k\)个1,
我们可以用 \(1000...(k个0)减 (k个0)....00001\)来表示,那麽k应小于等于0的个数。然后我就交了一发WA
这样是不对的,比如\(110010-100011=1111\),那麽一次类推,\(k<=a+b-2\),那麽构造的时候首先确定好用来产生k个1的1的位置,然后再安排其他的数。
然后被hack了
最后,当\(a=0,b=1,k=0\)时是成立的,所以这里我们需要对一些特殊的数据点进行特殊处理,即\(a=0,b=1,k=0时\)的特殊处理,然后就A了。
教训:对于最小的特殊数据不妨用特判处理更保险
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<map>
#include<bitset>
#include<vector>
#include<string>
#include<set>
using namespace std;
#define rep(i,a,b) for(register int i=a;i<=b;++i)
#define rpe(i,a,b) for(register int i=a;i>=b;--i)
#define pts putchar('\n')
#define ptc putchar(' ')
#define pb push_back
typedef long long ll;
typedef unsigned long long ull;
const int inf=0x7f7f7f7f;
const ll linf=1e18;
const int maxn=2e5+9;
const int maxm=2e6+9;
const int mod=20101009;
const double PI=3.1415926;
const double eps=1e-7;
namespace IO{
ll read(){
ll a=1,b=0;char c=getchar();
while(c>'9'||c<'0'){if(c=='-')a=-1;c=getchar();}
while(c>='0'&&c<='9'){b=(b<<3)+(b<<1)+c-'0';c=getchar();}
return a*b ;
}
void print (ll x){
if(x<0) putchar('-'),x=-x;
if(x>9) print(x/10);
putchar(x%10+'0');
}
}
using namespace IO;
int a,b,k;
int s1[maxn],s2[maxn];
bool solve(){
if(k==0){
rep(i,1,b) s1[i]=s2[i]=1;
return 1;
}
if(a==0) {return 0;}
if(b<=1) return 0;
if(k>a+b-2) return 0;
s1[1]=s2[1]=1;
s2[a+b]=1;
int pos=a+b-k;
s1[pos]=1;
int x=2;
rpe(i,a+b-1,1){
if(b-x>0){
if(i!=pos) s1[i]=s2[i]=1,x++;
}
else break;
}
return 1;
}
int main(){
#ifndef ONLINE_JUDGE
freopen("in1.txt","r",stdin);
// freopen("2.out","w",stdout);
#endif
a=read(),b=read(),k=read();
if(!solve()) puts("No");
else{
puts("Yes");
rep(i,1,a+b) print(s1[i]);
pts;
rep(i,1,a+b) print(s2[i]);
}
return 0;
}
E. Almost Fault-Tolerant Database
题目大意:给定n个m长度的序列,构造一个长度为m的序列,使得这个序列与每个序列的最多只有两个值不一样。
那麽需要构造的这个序列一定与第一个序列最多只有两个不一样的地方,那麽我们不妨暂定答案序列为第一个序列,然后对其进行修改。
那麽我们在往后遍历,如果没有偏差大于2个的情况直接输出,如果大于4个,那麽一定是不可能满足条件的,否则,我们就要记住当前不一样的位置,然后一个个枚举位置进行更改,当然在一次更改后如果可以,直接输出,否则再一次枚举位置进行更改,因为最多允许两个不一样,这里枚举两次就结束了。如果最后没有输出就是\(No\),有输出就是\(Yes\).
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<map>
#include<bitset>
#include<vector>
#include<string>
#include<set>
using namespace std;
#define rep(i,a,b) for(register int i=a;i<=b;++i)
#define rpe(i,a,b) for(register int i=a;i>=b;--i)
#define pts putchar('\n')
#define ptc putchar(' ')
#define pb push_back
typedef long long ll;
typedef unsigned long long ull;
const int inf=0x7f7f7f7f;
const ll linf=1e18;
const int maxn=25e4+9;
const int maxm=2e6+9;
const int mod=20101009;
const double PI=3.1415926;
const double eps=1e-7;
namespace IO{
ll read(){
ll a=1,b=0;char c=getchar();
while(c>'9'||c<'0'){if(c=='-')a=-1;c=getchar();}
while(c>='0'&&c<='9'){b=(b<<3)+(b<<1)+c-'0';c=getchar();}
return a*b ;
}
void print (ll x){
if(x<0) putchar('-'),x=-x;
if(x>9) print(x/10);
putchar(x%10+'0');
}
}
using namespace IO;
int n,m;
vector<int>G[maxn],ans,pos,pos1;
int id1,id2;
bool check(){
int num;
rep(i,2,n){
num=0;
rep(j,1,m) num+=(G[i][j]!=ans[j]);
if(num>2) return 0;
}
return 1;
}
void print_ans(){
puts("Yes");
rep(i,1,m) print(ans[i]),ptc;
exit(0);
}
int main(){
#ifndef ONLINE_JUDGE
freopen("in2.txt","r",stdin);
// freopen("2.out","w",stdout);
#endif
n=read();m=read();
rep(i,1,n){
G[i].resize(m+1);
rep(j,1,m) G[i][j]=read();
}
ans=G[1];
if(m<=2) print_ans();
rep(i,2,n){
pos.clear();
rep(j,1,m) if(ans[j]!=G[i][j]) pos.pb(j);
if(pos.size()>=3) {id1=i;break;}
}
if(pos.size()<3) print_ans();
if(pos.size()>4) {puts("No");exit(0);}
for(int x :pos){
ans[x]=G[id1][x];
rep(i,2,n){
pos1.clear();
rep(j,1,m){
if(ans[j]!=G[i][j]) pos1.pb(j);
}
if(pos1.size()>=3){
id2=i;
break;
}
}
if(pos1.size()<3) print_ans();
else if(pos1.size()==3){
for(int y : pos1){
int tmp=ans[y];
ans[y]=G[id2][y];
if(check()) print_ans();
ans[y]=tmp;
}
}
ans[x]=G[1][x];
}
puts("No");
}
赛后小结
这场比赛因为D被hack,痛失大量的可加rating,同时前几个题没有一遍A,有些失误。以后做题,一些小的极端数据不妨直接特判,减少被hack的风险,同时自己再多试几组数据,减少WA的次数。