2022河南萌新联赛第(一)场

A Alice and Bob

先把数字进行质因数分解,分解成 n 堆数字,每堆有 k 个,这样就变成了反尼姆博弈问题

反尼姆博弈的先手必胜条件有两个

  1. 异或和为 0 , 所有数等于 1
  2. 异或和不为 0 ,且有数大于 1
#include<bits/stdc++.h>
#define int  long long
using namespace std;

int n , cnt , res;
vector< int > c;

int32_t main() {
    cin >> n;
    for( int i = 2 ; i < sqrt(n) ; i ++ ){
        if( n % i == 0 ){
            cnt = 0;
            while( n % i == 0 ) n /= i , cnt ++;
            c.push_back( cnt );
        }
    }
    if( n > 1 )  c.push_back(1);

    int f = 0 ;
    for( auto it : c ){
        res ^= it;
        if( it > 1 ) f = 1;
    }
    // 先手必胜条件
    // 1. 异或和为 0 , 所有数等于 1
    // 2. 异或和不为 0 ,且有数大于 1 
    if( ( res != 0 && f == 1 ) || ( res == 0 && f == 0 ) )
        cout << "Alice win\n";
    else
        cout << "Bob win\n";
    return 0;
}

B 打对子

判断一下对子的数量

#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 = 1e6+5;
int n , cnta , cntb;
string sa , sb;
map< char , int > va , vb;
int32_t main() {
    cin >> n >> sa >> sb ;
    for( auto it : sa )
        va[it] ++ ;
    for( auto it : sb )
        vb[it] ++;
    for( auto [ k , v ] : va )
        cnta += v % 2;
    for( auto [ k , v ] : vb )
        cntb += v % 2;
    cout << cnta <<"\n" << (cnta < cntb ? "YES\n" : "NO\n" );
    return 0;
}

D 纪念品领取

模拟一下这个过程就好了,我是先一直把人往后放最后整理一下

#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 = 1e6+5;
int n , m , a[N] , ed;
vector< pair<int,int> > ve;
vector< int> res;
int32_t main() {
    ed = n = read() , m = read() ;
    for( int i = 1 ; i <= n ; i ++ ) a[i] = i;
    for( int i = 1 , x ; i <= m; i ++ ){
        x = read() , ed ++ , a[x] = ed;
    }
    for( int i = 1 ; i <= n ; i ++ )
        ve.push_back( { a[i] , i } );
    sort( ve.begin() , ve.end() );
    for( int i = 0 ; i < 5 ; i ++ ){
        res.push_back( ve[i].second );
    }
    std::sort(res.begin(), res.end());
    for( auto it : res ){
        cout << it << " ";
    }
    return 0;
}

F 买车

直接从七点开始 bfs

#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 = 1e5+5;
int n , m , t ;
queue< pair< int , int > > q;
set<int> shop;
map< int , int > cars;
vector< int > cur;

int32_t main() {
    n = read() , m = read() , t = read();
    for( int x , y ; m ; m -- )
        x = read() , y = read() , shop.insert(x) , cars[x] = max( cars[x] , y );

    for( auto it : shop ){
        if( it > t ) break;
        q.push( { it , 0 } ) , cur.push_back(it);
    }
    for( auto it : cur ) shop.erase(it);
    while( q.size() ){
        int x = q.front().first , k = q.front().second; q.pop();
        if( x + cars[x] >= n ) {
            cout << k + 1 << endl;
            return 0;
        }
        cur.clear();
        for( auto it : shop ){
            if( it > x + cars[x] ) break;
            q.push( { it , k + 1 } ) , cur.push_back(it);
        }
        for( auto it : cur ) shop.erase(it);
    }
    cout << "-1\n";
    return 0;
}

G 热身小游戏

直接暴力就好了,在储存的时候存操作的位置和操作的值,然后在删除的时候判断一下操作的位置是否在范围内即可

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

const int N = 1e5+5 , mod = 1e9+7;
int q , op[N] ;
vector< pair< int , int > > mul , nxt;

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(){
    q = read();
    for( int i = 1 , l , r ; i <= q ; i ++ )
    {
        op[i] = read();
        if( op[i] == 1 ){
            l = read();
            mul.push_back({ i , l } );
        }
        else if( op[i] == 2 ){
            nxt.clear() , l = read() , r = read();
            for( auto it : mul )
                if( it.first < l || it.first > r ) nxt.push_back(it);
            mul = nxt;
        }
        else{
            l = 1;
            for( auto [ k , v ] : mul )
                l = ( l * v ) % mod;
            cout << l << endl;
        }
    }
}

I 巡逻机器人

相遇反向走直接忽视掉,然后暴力的枚举一下机器人走的过程就好了

#include<bits/stdc++.h>

using namespace std;

const int N = 1e6+5;
int vis[N] , p[N] , d[N] , n , m , cnt , tim ;

int read( int x ) {
    if( x == 1 ){
        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;
    }
    else{
        char ch = getchar();
        while( ch != 'R' && ch != 'L' ) ch = getchar();
        return ( ch == 'R' ? 1 : -1 );
    }
}
int32_t main() {
    n = read(1) , m = read(1);
    for( int i = 1 ; i <= m ; i ++ ) {
        p[i] = read(1) , d[i] = read(0);
        if( vis[ p[i] ] ) continue;
        vis[ p[i] ] = 1 , cnt ++;
    }
    while( cnt < n ){
        tim ++;
        for( int i = 1 ; i <= m ; i ++ ){
            p[i] += d[i];
            if( p[i] == n+1 ) p[i] = 1;
            if( p[i] == 0 ) p[i] = n;
            if( vis[ p[i] ] ) continue;
            vis[ p[i] ] = 1 , cnt ++;
        }

    }
    cout << tim << "\n";
    return 0;
}

J 樱果运输

做一个背包问题f[i][k]表示j量车k元钱最多能拉多少货物,然后我们在做的时候枚举一下最少能用的车辆数就好了

#include<bits/stdc++.h>

using namespace std;

const int N = 105 , M = 1e3+5;
int n , m , w[N] , t[N] , f[N][M];

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() {
    n = read() , m = read();
    for( int i = 1 ; i <= n ; i ++ )
        w[i] = read() , t[i] = read();
    for( int i = 1 ; i <= n ; i ++ )
    {
        for( int j = i ; j >= 1 ; j -- )
        {
            for( int k = 1000 ; k >= w[i] ; k -- ) 
                f[j][k] = max( f[j][k] , f[j-1][k-w[i]] + t[i] );
        }
    }
    for( int x , y , res ; m ; m -- ){
        x = read() , y = read() , res = -1;
        for( int i = 1 ; i <= n ; i ++ ){
            if( f[i][x] < y ) continue;
            res = i ;
            break;
        }
        cout << res << "\n";
    }
    return 0;
}

K 糟糕的一天

维护一下后缀最大值就好了

#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 = 1e6+5;
int n , a[N] , mx = -1e9-1 , res = 0;

int32_t main() {
    n = read();
    for( int i = 1 ; i <= n ; i ++ ) a[i] = read();
    for( int i = n ; i >= 1 ; i -- ){
        if( a[i] < mx ) res ++;
        else mx = a[i];
    }
    cout << res << endl;
    return 0;
}

E 聚会

当前已经可以组合出[1,x]未用的数字中最小的是a,有两种情况

  1. a > x + 1 那么x+1就无法组合出
  2. a<=x+1,那么就可以把当前的集合扩展为[1,x+a]
#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;
}

const int N = 1e5+5;
int n , a[N] , top = 0;

int32_t main() {
    n = read();
    for( int i = 1 ; i <= n ; i ++ ) a[i] = read();
    sort( a + 1 , a + 1 + n );
    for( int i = 1 ; i <= n ; i ++ ){
        if( a[i] > top + 1 ) break;
        else top += a[i];
    }
    cout << top + 1 << endl;
    return 0;
}
posted @ 2022-07-16 11:03  PHarr  阅读(46)  评论(0编辑  收藏  举报