2022河南萌新联赛第(一)场
A Alice and Bob
先把数字进行质因数分解,分解成 n 堆数字,每堆有 k 个,这样就变成了反尼姆博弈问题
反尼姆博弈的先手必胜条件有两个
- 异或和为 0 , 所有数等于 1
- 异或和不为 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
,有两种情况
a > x + 1
那么x+1
就无法组合出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;
}