牛客小白月赛55

A 至至子的等差中项

#include<bits/stdc++.h>
using namespace std;

int32_t main(){
    int a , b;
    cin >> a >> b;
    cout << b * 2 - a << "\n";
}

B 至至子的按位与

如果在二进制下按位考虑。如果a,b某位都是1的话c的这一位自然也是1。如果都是0的话,c0,1都可但是尽可能的大所以选择1。如果不相同的情况就只能选择0了。

#include<bits/stdc++.h>
#define int long long
using namespace std;

int read(){
    int x = 0 , f = 1 , ch = getchar();
    while( (ch < '0' || ch > '9') && ch != '-' ) ch = getchar();
    if( ch == '-' ) f = -1 , ch = getchar();
    while( ch >= '0' && ch <= '9' ) x = ( x << 3 ) + ( x << 1 ) + ch - '0' , ch = getchar();
    return x * f;
}

int32_t main(){
    int a = read() , b = read() , c = 0;
    vector<int> v;

    for( int i = 0 ; i < 63 ; i ++ ){
        if( (a&1) == (b&1) ) c += ( 1ll << i );
        a >>= 1 , b >>= 1 ;
    }
    cout << c << "\n";
}

C 至至子的斐波那契

斐波那契第88项就大于1e18了,所以先计算出足够长斐波那契数列,然后对于每个询问二分就好了

#include<bits/stdc++.h>
#define int long long
using namespace std;

int read(){
    int x = 0 , f = 1 , ch = getchar();
    while( (ch < '0' || ch > '9') && ch != '-' ) ch = getchar();
    if( ch == '-' ) f = -1 , ch = getchar();
    while( ch >= '0' && ch <= '9' ) x = ( x << 3 ) + ( x << 1 ) + ch - '0' , ch = getchar();
    return x * f;
}

int32_t main(){
    int n = 2;
    vector<int> feb;
    feb.push_back(0) , feb.push_back(1) ,feb.push_back(1);
    for( ; feb.back() < 1e18 ;  n ++ )
        feb.push_back( feb[n] + feb[n-1] );

    for( int T = read() , x , t ; T ; T -- ){
        x = read();
        t = lower_bound( feb.begin() , feb.end() , x ) - feb.begin();
        if( feb[t] - x >= x - feb[t-1]  ) t --;
        cout << t << "\n";
    }
}

D 至至子的鸿门宴

一共只能取\(\sum_i=1^n(a_i-i)\)个,每次只能取一个。易知取的顺序没有影响,所以一共能取奇数个先手必胜。

#include<bits/stdc++.h>
#define int long long
using namespace std;

int read(){
    int x = 0 , f = 1 , ch = getchar();
    while( (ch < '0' || ch > '9') && ch != '-' ) ch = getchar();
    if( ch == '-' ) f = -1 , ch = getchar();
    while( ch >= '0' && ch <= '9' ) x = ( x << 3 ) + ( x << 1 ) + ch - '0' , ch = getchar();
    return x * f;
}

int32_t main(){
    int sum = 0 , n = read();
    for( int i = 1 , a ; i <= n ; i ++ )
        a = read() - i , sum += a;
    if( sum & 1 ) cout << "ZZZ\n";
    else cout << "SSZ\n";
}

E 至至子的长链剖分

这是一个构造题目,要构造一棵树,每一个点有一个权值,且父节点的权值必须比子节点大,叶子节点权值只能为零。

那么首先我们就要先找到根节点,发现如果根节点不唯一,这无解。

然后我们判断每一个权值为i的节点数如果比i-1少,那么一定无解。

再次基础上,我们按照全职递减的方法连成多个链,把每一条链都插在根节点上就好。

#include<bits/stdc++.h>

using namespace std;


int read() {
    int x = 0, f = 1, ch = getchar();
    while ((ch < '0' || ch > '9') && ch != '-') ch = getchar();
    if (ch == '-') f = -1, ch = getchar();
    while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
    return x * f;
}

const int N = 2e5+5;
int fa[N] ;//每个节点的父亲
vector<int> h[N];//每种权值点的集合


void solve(){
    int n = read() , m = -1;
    fill( fa+1 , fa+1+n , 0 );
    fill( h , h+1+n , vector<int>() );
    for( int i = 1 , x ; i <= n ; i ++ )
        x = read() , h[x].push_back(i) , m = max( m , x );
    if( h[m].size() > 1 ){
        cout << "-1\n";
        return;
    }
    for( int i = 2 ; i <= m ; i ++ )
        if( h[i].size() > h[i-1].size() ) {
            cout << "-1\n";
            return;
        }
    int root = h[m][0];
    fa[root] = root , h[m].pop_back();
    while( m >= 0 ){
        while( h[m].empty() ) m --;
        if( m < 0 ) break;
        int f = h[m].back();//链的起点
        fa[f] = root , h[m].pop_back();
        for( int i = m - 1 , t ; i >= 0 ; i -- )//构造链
            t = h[i].back() , h[i].pop_back() , fa[t] = f , f = t;
    }
    cout << root << "\n";
    for( int i = 1 ; i <= n ; i ++ )
        if( fa[i] != i ) cout << fa[i] << " " << i << "\n";
}

int32_t main() {
    for( int T = read() ; T ; T -- )
        solve();
}
posted @ 2022-11-10 10:39  PHarr  阅读(15)  评论(0编辑  收藏  举报