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(取决于单增的单调栈还是单减的单调栈)