居然是大苹果带出来的兵?直接 biu 了
KingGojianOfYue · · 题解
感觉不像人类了(尽管场了),第一次写三个递归函数嵌套,这不比 cake 难?
如果想让你期望步数增多,那么
先把整个序列 shuffle 一下,再三个三个分组:每次如果结果为
-
对于和为
1 的三元组序列:把第一个元素按如上方式处理即可得到每个三元组序列中第一个元素的值,对于每个三元组来讲:如果第一个数为0 ,那么后面两个数一定为1 ,否则后面两个数和为1 ,把这种情况的每两个数构成一个二元组放在一个序列中; -
对于和为
2 的三元组序列:同理; -
对于如上和为
1 的二元组序列:把第一个元素三个三个分组:依旧是每次如果结果为0 或3 ,那么肯定是全0 或全1 ,然后分为和为1 的三元组序列与和为2 的三元组序列两部分。
分析一下期望:设对于一个长度为
可得
实现时由于递归出来的序列长度不总是
代码:
#include<bits/stdc++.h>
using namespace std;
int dream(int x,int y,int z);
vector<bool>ans;
int c0,c1;mt19937 rnd(time(NULL));
struct node2{int x,y;};
struct node3{int x,y,z;};
inline void solve2(vector<node2>v);
inline void solve30(vector<node3>v);
inline void solve31(vector<node3>v);
inline void solve2(vector<node2>v){
if(v.empty())return;
int n=v.size()%3;
for(int i=0;i<n;++i)ans[v[i].x]=dream(c0,c1,v[i].x)-ans[c0]-ans[c1];
vector<node3>v0,v1;
for(int i=n;i<(int)v.size();i+=3){
auto a0=v[i],a1=v[i+1],a2=v[i+2];
int x=dream(a0.x,a1.x,a2.x);
if(x==0)ans[a0.x]=0,ans[a1.x]=0,ans[a2.x]=0;
else if(x==3)ans[a0.x]=1,ans[a1.x]=1,ans[a2.x]=1;
else if(x==1)v0.emplace_back(node3{a0.x,a1.x,a2.x});
else if(x==2)v1.emplace_back(node3{a0.x,a1.x,a2.x});
}solve30(v0),solve31(v1);
for(auto it:v)ans[it.y]=ans[it.x]^1;
}
inline void solve30(vector<node3>v){
if(v.empty())return;
int n=v.size()%3;
vector<node2>v2;vector<node3>v0,v1;
for(int i=0;i<n;++i){
ans[v[i].x]=dream(c0,c1,v[i].x)-ans[c0]-ans[c1];
}
for(int i=n;i<(int)v.size();i+=3){
auto a0=v[i],a1=v[i+1],a2=v[i+2];
int x=dream(a0.x,a1.x,a2.x);
if(x==0)ans[a0.x]=0,ans[a1.x]=0,ans[a2.x]=0;
else if(x==3)ans[a0.x]=1,ans[a1.x]=1,ans[a2.x]=1;
else if(x==1)v0.emplace_back(node3{a0.x,a1.x,a2.x});
else if(x==2)v1.emplace_back(node3{a0.x,a1.x,a2.x});
}solve30(v0),solve31(v1);
for(auto it:v){
if(ans[it.x]==1)ans[it.y]=ans[it.z]=0;
else v2.emplace_back(node2{it.y,it.z});
}solve2(v2);
}
inline void solve31(vector<node3>v){
if(v.empty())return;
int n=v.size()%3;
vector<node2>v2;vector<node3>v0,v1;
for(int i=0;i<n;++i){
ans[v[i].x]=dream(c0,c1,v[i].x)-ans[c0]-ans[c1];
}
for(int i=n;i<(int)v.size();i+=3){
auto a0=v[i],a1=v[i+1],a2=v[i+2];
int x=dream(a0.x,a1.x,a2.x);
if(x==0)ans[a0.x]=0,ans[a1.x]=0,ans[a2.x]=0;
else if(x==3)ans[a0.x]=1,ans[a1.x]=1,ans[a2.x]=1;
else if(x==1)v0.emplace_back(node3{a0.x,a1.x,a2.x});
else if(x==2)v1.emplace_back(node3{a0.x,a1.x,a2.x});
}solve30(v0),solve31(v1);
for(auto it:v){
if(ans[it.x]==0)ans[it.y]=ans[it.z]=1;
else v2.emplace_back(node2{it.y,it.z});
}solve2(v2);
}
std::vector<bool>solve(int n){
if(n==4){
int d=dream(0,1,2),c=dream(0,1,3),b=dream(0,2,3),a=dream(1,2,3);
int s=(d+c+b+a)/3;
d=s-d,c=s-c,b=s-b,a=s-a;
ans.push_back(a),ans.push_back(b),ans.push_back(c),ans.push_back(d);
return ans;
}ans.resize(n);
vector<int>p(n);
iota(p.begin(),p.end(),0);
shuffle(p.begin(),p.end(),rnd);
vector<node3>v0,v1;
v0.clear(),v1.clear();
for(int i=0;i<n;i+=3){
int x=dream(p[i],p[i+1],p[i+2]);
if(x==0)ans[p[i]]=0,ans[p[i+1]]=0,ans[p[i+2]]=0,c0=p[i],c1=p[i+1];
else if(x==3)ans[p[i]]=1,ans[p[i+1]]=1,ans[p[i+2]]=1,c0=p[i],c1=p[i+1];
else if(x==1)v0.emplace_back(node3{p[i],p[i+1],p[i+2]});
else if(x==2)v1.emplace_back(node3{p[i],p[i+1],p[i+2]});
}solve30(v0),solve31(v1);
return ans;
}