Codeforces Round 669 (Div. 2) 题解 (ABC)
最近有点忙,这场就写到 C 吧,D 我口胡一下(懒得补)。
# A. Ahahahahahahahaha
题目读错了,没看到 $n$ 是偶数(藏在这么隐蔽的地方),题目就复杂好多但是居然有解。
先说正解,因为只有偶数,如果 1 的个数小于等于 $\dfrac n 2$,就删掉所有的 1,否则删掉所有 0,并且在 1 的个数是奇数的时候删掉一个 1。
(然后讲一下新题目,不看也罢)n 不一定是偶数。找到连续的两个 1 或者连续的两个 0,无视它们就不会对结果产生影响。删掉它们后(并不是真的删掉因为最后还是要输出的),序列只可能是 0101.. 或者 1010..(0 和 1 交替出现)。对于 0101..,删掉所有的 1 就行了。对于 1010..,我们删掉第一个 0 和第 3 个以及之后所有的 1,变成 11000..,这样删掉的数量不超过 n/2。还有一个特殊情况 10,要删掉第一个 1。
为什么 A 题能被我想得这么复杂,实属迷惑行为。
//#pragma GCC optimize(3)
#include <bits/stdc++.h>
using namespace std;
#define repeat(i,a,b) for(int i=(a),_=(b);i<_;i++)
#define repeat_back(i,a,b) for(int i=(b)-1,_=(a);i>=_;i--)
#define mst(a,x) memset(a,x,sizeof(a))
#define fi first
#define se second
mt19937 rnd(chrono::high_resolution_clock::now().time_since_epoch().count());
typedef long long ll; typedef double lf; typedef pair<ll,ll> pii;
int cansel_sync=(ios::sync_with_stdio(0),cin.tie(0),0); ll read(); lf readf();
const int inf=~0u>>2; const ll INF=~0ull>>2; const lf pi=acos(-1.0);
template<typename T> void operator<<(vector<T> &a,T b){a.push_back(b);}
const int N=200010; const ll mod=(1?1000000007:998244353); ll mul(ll,ll,ll); ll qpow(ll,ll,ll);
#define int ll
vector<int> stk;
int a[N],ans[N];
void Solve(){
int n=read(); stk.clear();
repeat(i,0,n){
a[i]=read(); stk<<i; //"<<" means push_back
if(stk.size()>=2 && a[stk.rbegin()[0]]==a[stk.rbegin()[1]])
stk.pop_back(),stk.pop_back();
}
fill(ans,ans+n,1);
if(stk.size()==2)
for(auto i:stk)ans[i]=!a[i];
else if(stk.size()>=2)ans[stk[1]]=0;
repeat(i,3,stk.size())if(a[stk[i]])ans[stk[i]]=0;
cout<<accumulate(ans,ans+n,0)<<endl;
repeat(i,0,n)if(ans[i])cout<<a[i]<<' ';
cout<<endl;
}
signed main(){
//freopen("data.txt","r",stdin);
int T=1; T=read();
repeat(ca,1,T+1){
Solve();
}
return 0;
}
ll read(){
ll x; if(scanf("%lld",&x)==-1)exit(0);
return x;
}
lf readf(){
lf x; if(scanf("%lf",&x)==-1)exit(0);
return x;
}
ll mul(ll a,ll b,ll m=mod){
return a*b%m;
}
ll qpow(ll a,ll b,ll m=mod){
ll ans=1;
for(;b;a=mul(a,a,m),b>>=1)
if(b&1)ans=mul(ans,a,m);
return ans;
}
# B. Big Vova
第一个数显然是原序列的最大值。如果处理出了前 i 个数,我们计算前 i 个数的 gcd 为 d,找到剩下的数里 gcd(d,a[i]) 最大的 a[i] 作为第 i+1 个数即可。
//#pragma GCC optimize(3)
#include <bits/stdc++.h>
using namespace std;
#define repeat(i,a,b) for(int i=(a),_=(b);i<_;i++)
#define repeat_back(i,a,b) for(int i=(b)-1,_=(a);i>=_;i--)
#define mst(a,x) memset(a,x,sizeof(a))
#define fi first
#define se second
mt19937 rnd(chrono::high_resolution_clock::now().time_since_epoch().count());
typedef long long ll; typedef double lf; typedef pair<ll,ll> pii;
int cansel_sync=(ios::sync_with_stdio(0),cin.tie(0),0); ll read(); lf readf();
const int inf=~0u>>2; const ll INF=~0ull>>2; const lf pi=acos(-1.0);
template<typename T> void operator<<(vector<T> &a,T b){a.push_back(b);}
const int N=200010; const ll mod=(1?1000000007:998244353); ll mul(ll,ll,ll); ll qpow(ll,ll,ll);
#define int ll
vector<int> a,ans;
void Solve(){
int n=read(); a.clear(); ans.clear();
repeat(i,0,n)a<<read();
int now=*max_element(a.begin(),a.end());
repeat(i,0,n){
int p=max_element(a.begin(),a.end(),[&](int x,int y){
return __gcd(now,x)<__gcd(now,y);
})-a.begin();
now=__gcd(now,a[p]);
ans<<a[p];
swap(a[p],a.back());
a.pop_back();
}
for(auto i:ans)cout<<i<<' ';
cout<<endl;
}
signed main(){
//freopen("data.txt","r",stdin);
int T=1; T=read();
repeat(ca,1,T+1){
Solve();
}
return 0;
}
ll read(){
ll x; if(scanf("%lld",&x)==-1)exit(0);
return x;
}
lf readf(){
lf x; if(scanf("%lf",&x)==-1)exit(0);
return x;
}
ll mul(ll a,ll b,ll m=mod){
return a*b%m;
}
ll qpow(ll a,ll b,ll m=mod){
ll ans=1;
for(;b;a=mul(a,a,m),b>>=1)
if(b&1)ans=mul(ans,a,m);
return ans;
}
# C. Chocolate Bunny
因为模的运算很头疼,但是一个非常有用的性质直接能秒掉这题。如果有两个数 a,b (a≠b),如果 a%b > b%a,那么 a 的值就是 a%b,否则 b 的值是 b%a。
上述操作可以消耗两次询问直接确定一个数的值。我们每次拿出两个未知的位置进行两次询问,也就是说每次都有一个未知的数变成已知的数。只要 2(n-1) 次询问后即可确定 n-1 个数,最后那个数就不用说了。
//#pragma GCC optimize(3)
#include <bits/stdc++.h>
using namespace std;
#define repeat(i,a,b) for(int i=(a),_=(b);i<_;i++)
#define repeat_back(i,a,b) for(int i=(b)-1,_=(a);i>=_;i--)
#define mst(a,x) memset(a,x,sizeof(a))
#define fi first
#define se second
mt19937 rnd(chrono::high_resolution_clock::now().time_since_epoch().count());
typedef long long ll; typedef double lf; typedef pair<ll,ll> pii;
int cansel_sync=(ios::sync_with_stdio(0),cin.tie(0),0); ll read(); lf readf();
const int inf=~0u>>2; const ll INF=~0ull>>2; const lf pi=acos(-1.0);
template<typename T> void operator<<(vector<T> &a,T b){a.push_back(b);}
const int N=200010; const ll mod=(1?1000000007:998244353); ll mul(ll,ll,ll); ll qpow(ll,ll,ll);
#define int ll
int ans[N];
int query(int x,int y){
cout<<"? "<<x<<' '<<y<<endl; cout.flush();
int a; cin>>a;
cout<<"? "<<y<<' '<<x<<endl; cout.flush();
int b; cin>>b;
if(a>b){ans[x]=a; return y;}
else {ans[y]=b; return x;}
}
void Solve(){
int n; cin>>n;
int p=1;
repeat(i,2,n+1)
p=query(p,i);
cout<<"! ";
repeat(i,1,n+1){
if(ans[i]==0)ans[i]=n;
cout<<ans[i]<<' ';
}
cout<<endl;
}
signed main(){
//freopen("data.txt","r",stdin);
int T=1; //T=read();
repeat(ca,1,T+1){
Solve();
}
return 0;
}
ll read(){
ll x; if(scanf("%lld",&x)==-1)exit(0);
return x;
}
lf readf(){
lf x; if(scanf("%lf",&x)==-1)exit(0);
return x;
}
ll mul(ll a,ll b,ll m=mod){
return a*b%m;
}
ll qpow(ll a,ll b,ll m=mod){
ll ans=1;
for(;b;a=mul(a,a,m),b>>=1)
if(b&1)ans=mul(ans,a,m);
return ans;
}
D 题,这个性质很容易(并不)想到单调栈。单调栈弹出的数和当前正在访问的数就刚好可以构成题目中的规则 2 或者规则 3(取决于单增的单调栈还是单减的单调栈)。