2023 Xiangtan Unversity Freshman Conteset
A. 签到啦
排序做就好了
#include <bits/stdc++.h>
using namespace std;
#define int long long
void solve(){
int n , w , res = 0;
cin >> n >> w;
vector<int> a(n);
for( auto & i : a ) cin >> i;
sort( a.begin() , a.end() , greater<int>() );
for( auto i : a ){
w -= i , res ++;
if( w <= 0 ) break;
}
cout << res << "\n";
}
int32_t main(){
ios::sync_with_stdio(false);
cin.tie(nullptr) , cout.tie(nullptr);
int t;
cin >> t;
while( t -- )
solve();
return 0;
}
B. 熙巨打票
首先如果\(a \le b\)就可以一直不间断的打印。否则除第一张票之外每\(a+b\)的时间可以打印两张票。
#include <bits/stdc++.h>
using namespace std;
#define int long long
void solve(){
int a , b , n;
cin >> a >> b >> n;
if( a <= b ) cout << b * n << "\n";
else{
if( n == 1 ) cout << b << "\n";
else if ( n & 1 ) cout << b + (a+b) * (n/2) << "\n";
else cout << b + (a+b) * (n/2) - a << "\n";
}
return ;
}
int32_t main(){
ios::sync_with_stdio(false);
cin.tie(nullptr) , cout.tie(nullptr);
int t;
cin >> t;
while( t -- )
solve();
return 0;
}
C. 三元分配
多写几个特判就好了。
首先如果总和是奇数,则一定不行。
当总和是偶数时,可以分成两种情况。如果全是偶数,则组内配对即可。否则一定是两个奇数一个偶数,此时要求奇数组各拿出一个和偶数里面进行配对。当然有两种特殊情况,一种是两个奇数和为2,还有一种是偶数为 0。
#include <bits/stdc++.h>
using namespace std;
#define int long long
bool check( int x ){
if( x == 0 || x == 1 ) return false;
for( int i = 2 ; i*i <= x ; i ++)
if( x % i == 0 ) return false;
return true;
}
void solve(){
int a , b , c;
cin >> a >> b >> c;
if( (a+b+c) % 2 ){
cout << "P\n";
return ;
}
if( a % 2 == 0 && b % 2 == 0 && c % 2 == 0 ){
cout << "R\n";
return;
}
if( a % 2 == 0 ) swap( a , c );
if( b % 2 == 0 ) swap( b , c );
if( ( c > 0 && check( a + c ) && check( b + c )) || a + b == 2 ) {
cout << "R\n";
}else{
cout << "P\n";
}
return ;
}
int32_t main(){
ios::sync_with_stdio(false);
cin.tie(nullptr) , cout.tie(nullptr);
int t;
cin >> t;
while( t -- )
solve();
return 0;
}
D. "逆"天求和
等差数列求和公式?
#include <bits/stdc++.h>
using namespace std;
#define int long long
bool check( int x ){
if( x == 0 || x == 1 ) return false;
for( int i = 2 ; i*i <= x ; i ++)
if( x % i == 0 ) return false;
return true;
}
void solve(){
int a;
cin >> a;
cout << a*(a-1)/2 << "\n";
return ;
}
int32_t main(){
ios::sync_with_stdio(false);
cin.tie(nullptr) , cout.tie(nullptr);
int t;
cin >> t;
while( t -- )
solve();
return 0;
}
E. 读中国数字
模拟题,很讨厌。
写一个函数用来处理四位数字。然后把原数拆开。
#include <bits/stdc++.h>
using namespace std;
#define int long long
string f(int x) {
if (x == 0) return "0";
int a, b, c, d;
a = x % 10, x /= 10;
b = x % 10, x /= 10;
c = x % 10, x /= 10;
d = x % 10, x /= 10;
string ans = "";
if (d != 0) ans += '0' + d, ans += 'K';
else ans += "0";
if (c != 0) ans += '0' + c, ans += 'B';
else if (ans != "" && ans.back() != '0') ans += '0';
if (b != 0) ans += '0' + b, ans += 'T';
else if (ans != "" && ans.back() != '0') ans += '0';
if (a != 0) ans += '0' + a;
else if (ans != "" && ans.back() != '0') ans += '0';
while (ans.back() == '0') ans.resize(ans.size() - 1);
return ans;
}
void solve() {
int n;
string x, y, z;
cin >> n;
if (n == 0) {
cout << "0\n";
return;
}
x = f(n % 10000), n /= 10000;
y = f(n % 10000), n /= 10000;
z = f(n % 10000), n /= 10000;
string s = "";
if (z != "0") s += z + 'Y';
if (y != "0") s += y + 'W';
if (x != "0") s += x;
while (s.front() == '0') s = s.substr(1);
while (s.back() == '0') s.resize(s.size() - 1);
cout << s << "\n";
}
int32_t main() {
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
int t;
cin >> t;
while (t--)
solve();
return 0;
}
F. 您有一封新邮件待接收
建有向图,跑 bfs,如果某个人收信次数大于总人数就说明他在某一个环上。为什么,因为如果他不在环上,最多也就是总人数次收到信。
#include <bits/stdc++.h>
using namespace std;
#define int long long
void solve() {
int n, m;
cin >> n >> m;
vector<int> vis(n + 1);
vector<string> name(n + 1);
for (int i = 1; i <= n; i++)
cin >> name[i];
vector<vector<int>> e(n + 1);
for (int i = 1, k; i <= n; i++) {
cin >> k;
e[i] = vector<int>(k);
for (auto &j: e[i]) cin >> j;
}
queue<int> q;
q.push(m);
vis[m] = -1;
while( !q.empty() ){
auto u = q.front();
q.pop();
if( vis[u] > n ) continue;
vis[u] ++;
for( auto v : e[u] ){
if( vis[v] > n ) continue;
q.push(v);
}
}
vector<string> res;
for( int i = 1 ; i <= n ; i ++ )
if( vis[i] > n ) res.push_back(name[i]);
if( res.empty() ){
cout << "No one is disturbed!\n";
return;
}
cout << res.size() << "\n";
for( auto i : res )
cout << i << " ";
cout << "\n";
return ;
}
int32_t main() {
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
int t;
cin >> t;
while (t--)
solve();
return 0;
}
H. 我爱XTU
一种很老的套路了,属于是又复习了一下。
用三个前缀和维护每种字母出现的次数,只考虑XT
的情况下可以得到\(X[r]-X[l-1]=T[r]-T[l-1]\)可以推出\(X[r]-T[r] =X[l-1]-T[l-1]\)。
稍微扩展一下,用个桶计数就好了。
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define mp make_pair
void solve(){
string s;
cin >> s;
int n = s.size();
vector<int> x(n+1) , t(n+1) , u(n+1);
for( int i = 1 ; i <= n ; i ++ ){
if( s[i-1] == 'X' ) x[i] ++;
else if( s[i-1] == 'T' ) t[i] ++;
else u[i] ++;
}
map< pair<int,int> , int> cnt;
for( int i = 1 ; i <= n ; i ++ )
x[i] += x[i-1] , t[i] += t[i-1] , u[i] += u[i-1];
for( int i = 0 ; i <= n ; i ++ )
cnt[ mp( x[i] - t[i] , t[i] - u[i] ) ] ++;
int res = 0;
for( auto [k,v] : cnt )
res += v*(v-1)/2;
cout << res << "\n";
return ;
}
int32_t main(){
ios::sync_with_stdio(false);
cin.tie(nullptr) , cout.tie(nullptr);
int t;
cin >> t;
while( t -- )
solve();
return 0;
}
I. 小黑的鸡脚plus
\(f[i][j]=\max(f[i-1][j],f[i][j-1],f[i-d][j-v[i]+v[i-d]]+1)\)
\(v[i]\)表示前缀\(0\)的个数。
#include <bits/stdc++.h>
using namespace std;
#define int long long
void solve() {
int n , k , d;
string s;
cin >> k >> d >> s;
n = s.size();
vector<int> v(n+1);
for( int i = 1 ; i <= n ; i ++ )
v[i] = v[i-1] + (s[i-1] == '0' );
vector<vector<int>> f( n+1 , vector<int>(k+1 , 0 ) );
for( int i = 1 ; i <= n ; i ++ ){
for( int j = 0 ; j <= k ; j ++ ){
f[i][j] =f[i-1][j];
if( j > 0 ) max( f[i][j] , f[i][j-1] );
if( i >= d && v[i] - v[i-d] <= j )
f[i][j] = max( f[i][j] , f[i-d][ j - v[i]+v[i-d] ] + 1 );
}
}
cout << f[n][k] << "\n";
}
int32_t main() {
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
int t;
cin >> t;
while (t--)
solve();
return 0;
}
J. 组队
其实题解说的很玄乎,就搜索就可以了。用后缀做个剪枝就行了
#include <bits/stdc++.h>
using namespace std;
#define int long long
int n, m, res;
typedef bitset<60> state;
vector<state> a, suf;
void dfs(int i, state d) {
if (d.count() == m) {
res++;
return;
}
if (i == n + 1) return;
if ((d | suf[i]).count() < m) return;
if ((d & a[i]).count() == 0)
dfs(i + 1, d | a[i]);
dfs(i + 1, d);
return;
}
void solve() {
cin >> n >> m, res = 0;
a = vector<state>(n + 1), suf = vector<state>(n + 1);
for (int i = 1, k; i <= n; i++) {
cin >> k;
for (int x; k; k--) cin >> x, x--, a[i][x] = 1;
}
suf[n] = a[n];
for (int i = n - 1; i >= 1; i--) suf[i] = suf[i + 1] | a[i];
dfs(1, state(0));
cout << res << "\n";
return;
}
int32_t main() {
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
int t;
cin >> t;
while (t--)
solve();
return 0;
}