天天看点

Codeforces Round #651 (Div. 2)【A - F】

题目链接:https://codeforces.com/contest/1370

最后的F题卡了半天,不过最后还是找到了问题。补了3.5题~

A - F 题解

    • A. Maximum GCD
    • B. GCD Compression
    • C. Number Game
    • D. Odd-Even Subsequence
    • E. Binary Subsequence Rotation
    • F2. The Hidden Pair (Hard Version)

A. Maximum GCD

设 g c d ( a , b ) = k , a = x k , b = y k , x 与 y 互 质 设gcd(a,b)=k ,a=xk,b=yk,x与y互质 设gcd(a,b)=k,a=xk,b=yk,x与y互质,想让k更大的话,x和y要尽量小,x=1,y=2正好是最小的。所以不难发现k=n/2

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<unordered_map>
#include<stack>
#include<set>
#include<algorithm>
#define ls k<<1,l,mid
#define rs k<<1|1,mid+1,r
#define FOR(i,l,r) for(int i=l;i<=r;i++)
#define ROF(i,l,r) for(int i=l;i>=r;i--)
#define pb(x) push_back(x)
#define mp(x,y) make_pair(x,y)
#define r(x) read(x)
#define rr(x,y) read(x);read(y)
#define rrr(x,y,z) read(x);read(y);read(z)
#define sss(str) scanf("%s",str+1)
#define ssf(x) scanf("%lf",&x)
#define aLL(x) x.begin(),x.end()
#define fi first
#define se second
using namespace std;
typedef long long LL;
typedef pair<int,int> pt;
const int N=2e5+5;
const int M=2e3+5;
const int INF=2e9;
const int sz=15;
const int mod=1e9+7;
const double eps = 1e-8;
const double pi= acos(-1);
template<class T>
inline void read(T &x)
{
    char c;x=1;
    while((c=getchar())<'0'||c>'9') if(c=='-') x=-1;
    T res=c-'0';
    while((c=getchar())>='0'&&c<='9') res=res*10+c-'0';
    x*=res;
}
int n,m;
char str[N];
int f[N];
int main()
{
    int t;
    r(t);
    while(t--){
        r(n);
        cout<<n/2<<endl;
    }
    return 0;
}
           

B. GCD Compression

假设有x个奇数,y个偶数。

根据小学的姿势,奇数+奇数=偶数,偶数+偶数=偶数。

这里一共有偶数个数,我们只需要让奇数和奇数匹配,偶数和偶数匹配【匹配不了的丢掉,多出来的丢一对】就好了

int n,m;
char str[N];
int f[N];
int main()
{
    int t;
    r(t);
    while(t--){
        r(n);
        vector<int> v1,v2;
        FOR(i,1,n*2){
            int a;
            r(a);
            if(a&1) v1.pb(i);
            else v2.pb(i);
        }
        int a=0,b=0,c=v1.size(),d=v2.size();
        if(v1.size()%2==0){
            if(v1.size()) a=2;
            else b=2;
        }
        else{
            c--;
            d--;
        }
        for(int i=a;i<c;i+=2){
            cout<<v1[i]<<' '<<v1[i+1]<<endl;
        }
        for(int i=b;i<d;i+=2){
            cout<<v2[i]<<' '<<v2[i+1]<<endl;
        }
    }
    return 0;
}
           

C. Number Game

找规律。

①:n=1,此时先手必输

②:n为奇数,此时先手必胜

③:n=2,先手必胜

④:把n质数分解,若含2个及以上的2,和其他质数,那必胜

⑤:只有一个2,如果其他质数多于1个,必胜,否则必输

⑥:必输

int n,m;
char str[N];
int f[N];
int main()
{
    int t;
    r(t);
    while(t--){
        r(n);
        int a=0;
        if(n&1){
            if(n==1) cout<<"FastestFinger\n";
            else cout<<"Ashishgup\n";
            continue;
        }
        if(n==2){
            cout<<"Ashishgup\n";
            continue;
        }
        while(n%2==0){
            a++;
            n>>=1;
        }
        if(n>1&&a>=2){
            cout<<"Ashishgup\n";
        }
        else if(n>1&&a>=1){
            bool flag=1;
            FOR(i,2,sqrt(n)){
                if(n%i==0){
                    flag=0;
                    break;
                }
            }
            if(!flag) cout<<"Ashishgup\n";
            else cout<<"FastestFinger\n";
        }
        else{
            cout<<"FastestFinger\n";
        }
    }
    return 0;
}
           

D. Odd-Even Subsequence

答案肯定是数组中的一个,二分答案,如果他可以携带的序列不少于k个,那肯定可以,再找更小的

【假如说答案在奇数/偶数段】偶数/奇数段随便都可以选,奇数/偶数段的数必须不大于这个答案

int n,m;
char str[N];
int f[N],g[N];
bool check(int x,bool tmp)
{
    int ans=0;
    FOR(i,1,n){
        if(tmp){
            ans++;
            tmp^=1;
        }
        else{
            if(f[i]<=g[x]){
                ans++;
                tmp^=1;
            }
        }
    }
    return ans>=m;
}
int main()
{
    rr(n,m);
    FOR(i,1,n){
        r(f[i]);
        g[i]=f[i];
    }
    sort(g+1,g+n+1);
    int l=1,r=n;
    int ans=0;
    while(l<=r){
        int mid=l+r>>1;
        if(check(mid,1)||check(mid,0)){
            ans=mid;
            r=mid-1;
        }
        else l=mid+1;
    }
    cout<<g[ans]<<endl;
    return 0;
}
           

E. Binary Subsequence Rotation

这题一直不知道怎么处理,原来要把串相同的地方去掉,之后就好做了。

剩下的就是0000110100101之类的串,我们每次操作都选择01010101来消除,这样消除的就是最大的。

int n,m;
char str1[N],str2[N];
int f[N];
int main()
{
    r(n);
    sss(str1);
    sss(str2);
    int a=0,b=0;
    FOR(i,1,n){
        if(str1[i]=='1') a++;
        if(str2[i]=='1') b++;
    }
    if(a!=b){
        cout<<-1<<endl;
        return 0;
    }
    vector<char> v;
    FOR(i,1,n){
        if(str1[i]!=str2[i]){
            v.pb(str1[i]);
        }
    }
    a=b=0;
    for(char x:v){
        if(x=='1'){
            a++;
            if(b) b--;
        }
        else{
            b++;
            if(a) a--;
        }
    }
    cout<<a+b<<endl;
    return 0;
}
           

F2. The Hidden Pair (Hard Version)

交互题,一开始就有思路。

首先找所有的点,输出一定是 这条路径中的一个点 和 这条路径的长度

然后我们以已知的这个点为根dfs,记录每层有什么点。

假设路径长度为k,答案之一距离根的max肯定大于等于(k+1)/2,我们就先找这个远的点。

下界为(k+1)/2,上界为k,二分查找即可。

得到这个点之后,再以这个点为根,那么距离这个点k距离的点集中再查询一次,即可得到另一个点

Codeforces Round #651 (Div. 2)【A - F】
int n,m;
char str[N];
int f[M];
vector<int> v[M],lvl[M],tmp;
pt query(vector<int> &tt)
{
    if(!tt.size()) return mp(-1,-1);
    cout<<"? "<<tt.size();
    for(int x:tt) cout<<" "<<x;
    cout<<endl;
    int a,b;
    cin>>a>>b;
    return mp(a,b);
}
void dfs(int x,int fa,int dep)
{
    m=max(m,dep);
    lvl[dep].pb(x);
    for(int y:v[x]){
        if(y!=fa){
            dfs(y,x,dep+1);
        }
    }
}
int main()
{
    int t;r(t);
    while(t--){
        r(n);
        m=0;
        tmp.clear();
        lvl[0].clear();
        FOR(i,1,n){
            v[i].clear();
            lvl[i].clear();
            tmp.pb(i);
        }
        FOR(i,1,n-1){
            int a,b;rr(a,b);
            v[a].pb(b);
            v[b].pb(a);
        }
        pt res=query(tmp);
        int root=res.fi,dep=res.se;
        dfs(root,0,0);
        int l=(dep+1)/2,r=min(m,dep),ans1;
        while(l<=r){
            int mid=l+r>>1;
            res=query(lvl[mid]);
            if(res.se==dep){
                ans1=res.fi;
                l=mid+1;
            }
            else r=mid-1;
        }
        FOR(i,0,n) lvl[i].clear();
        dfs(ans1,0,0);
        res=query(lvl[dep]);
        cout<<"! "<<ans1<<' '<<res.fi<<endl;
        string s;
        cin>>s;
    }
    return 0;
}
           

继续阅读