Codeforces Round #651 (Div. 2)A、B、C、D、E

题目
A题意:1到n中任选两个不同的数,gcd最大为大少。
解法:假设最大公约数为g,两个数不同所以两个数分别为g,2g.所以g=[\(\frac{n}{2}\)]

void solve(){
    int n ;
    cin >> n ;
    cout << n/2 << endl;
}

B题意:给出一个2n数组a,从a数组选出2(n-1),每次取两个数,其和加入b数组,使b数组构成一个n-1长且gcd(b1,b2,...,bn)>1,输出n-1对数在a数组的下标。
解法:gcd>1,考虑b数组全为偶数必然满足条件,把a数组分成奇偶两组,奇数两两配对,偶数两两配对,一定可以至少选出n-1对数的和为偶数。

void solve(){
    int n ;
    cin >> n ;
    vector<int>j , o;
    rep(i , 1 , n*2){
        cin >> a[i];
        if(a[i]%2==1){
            j.pb(i);
        }else{
            o.pb(i);
        }
    }
    vector<pii>v;
    for(int i = 1 ; i <= size(j)-1 ; i+=2){
        v.pb(mp(j[i] , j[i-1]));
    }
    for(int i = 1 ; i <= size(o)-1 ; i+=2){
        v.pb(mp(o[i] , o[i-1]));
    }
    for(int i = 0 ; i < n-1 ; i++){
        cout << v[i].fi << " " << v[i].se << endl;
    }
 
}

C题意:给出一个n,两个轮流进行以下两个操作中的一个最后不能操作的一方为败方,问谁为胜方。
1、n除以一个奇数因子
2、n(n>1)减去1
解法:1、如果为奇数先手赢。直接全拿走
2、质因子2只有1个,且其他质因子大于1个,则先手赢。策略:先手拿其他质因子数剩下一个,后手处于必败态
3、质因子2多于1个,且有其质他因子,则先手赢。策略:先手拿光其他质因子(一定为奇数),将大于2的偶数必败态转给了对手
4、2为先手赢
其他情况为后手胜。

void solve(){
    int n ;
    cin >> n ;
    if(n == 1){
        cout << "FastestFinger" << endl;
    }else if(n == 2){
        cout << "Ashishgup" << endl;
    }else{
        if(n % 2 == 1){
            cout << "Ashishgup" << endl;
        }else{
            int cnt = 0 ;
            while(n%2==0){
                n/=2;
                cnt++;
            }
            if(n == 1){//只有2质因子
                cout << "FastestFinger" << endl;
            }else{
                if(cnt == 1 && !is_prime(n)){//2质因子只有1个,其他质因子有多于1个
                    cout << "Ashishgup" << endl;
                }else if(cnt > 1){//质因子2多于1个,且有其他质因子
                    cout << "Ashishgup" << endl;
                }else{
                    cout << "FastestFinger" << endl;
                }
            }
        }
    }
}

D题意:给出一个n个数的数组,从中挑选k个数,形成一个新的数组,定义该数组的值为\(min(max(s_1,s_3,s_5..., s_2,s_4,s_6...))\),问该数组值为最小为多少。
解法:二分答案+贪心。分两种情况,如果该最小值为奇数贡献,遍历只要符合条件(小于二分枚举值)则加入奇数下标中,下一个数如果有就加入偶数下标,判断一下奇偶数的个数是否满足条件,偶数贡献同理。

const int maxn = 2e5+9;
int a[maxn];
int n , k ;
int lenj , leno ;

bool check(int x){
    int i = 1 , j = 0 , o = 0 ;
    while(i <= n){
        if(a[i] <= x){
            j++;
            if(i+1 <= n){
                i += 2 ;
                o++;
            }else{
                i++;
            }
        }else{
            i++;
        }
    }
    if(j >= lenj && o >= leno) return true;
    i = 2 , j = 1 , o = 0 ;
    while(i <= n){
        if(a[i] <= x){
            o++;
            if(i+1 <=n){
                i+=2;
                j++;
            }else{
                i++;
            }
        }else{
            i++;
        }
    }
    if(j >= lenj && o >= leno) return true;
    return false;
}

void solve(){
     cin >> n >> k ;
     lenj = (k+1)/2 , leno = k/2;
     rep(i , 1 , n){
         cin >> a[i];
     }
     int l = 1 , r = 1e9 ;
     while(r > l){
         int mid = (l + r) >> 1;
         if(check(mid)){
             r = mid ;
         }else{
             l = mid + 1;
         }
     }
     cout << r << endl;
}

E题意:给出n长两个字符数组a、b,可以取a数组的任意子序列进行顺时针旋转,sn->s1,s1->s2...。问a字符数组能否转变为b字符数组。
解法:首先判断a与b中相同字符数量是否相等。不相等则输出-1.
相同的字符不需要转动,所以旋转序列不选它们,因为所选序列为0101010或1010101.
10则a数组需要向右移,01b数组需要向左移。

void solve(){
     int n ;
     cin >> n ;
     scanf("%s%s" , a+1 , b+1);
     int x = 0 , ma = 0 , mi = 0 ;
     rep(i , 1 , n){
         x += a[i] - '0';
         x -= b[i] - '0';
         ma = max(ma , x);//往a需要右移ma位
         mi = min(mi , x);//b需要往左移mi位
     }
     int ans = ma - mi ;
     if(x != 0) ans = -1;
     cout << ans << endl;
}
posted @ 2020-06-22 11:31  无名菜鸟1  阅读(272)  评论(0编辑  收藏  举报