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;
}
posted @ 2023-05-22 22:28  PHarr  阅读(151)  评论(0编辑  收藏  举报