北华大学计算机程序设计算法提高训练营个人赛

A 洛姐打题日记

签到

#include<bits/stdc++.h>

using namespace std;

int32_t main() {
    string s;
    cin >> s;
    if( s == "AC" )
        cout << "Accepted\n";
    else if( s == "WA")
        cout << "Wrong Answer\n";
    else if( s == "RE")
        cout << "Runtime Error\n";
    else if( s == "CE")
        cout << "Compile Error\n";
    else if( s == "TLE")
        cout << "Time Limit Exceeded\n";
    else if( s == "PE")
        cout << "Presentation Error\n";
    else if( s == "MLE")
        cout << "Memory Limit Exceeded\n";
    return 0;
}

B 鸡兔同笼

小学数学,解一下方程就好了

#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;
}

void solve()
{
    int x = read() , y = read() , h = read(), f = read();
    int a = ( f - h * y ) / ( x - y ) , b = h - a;
    cout << a << " " << b << "\n";

}

int32_t main() {
    int t = read();
    while( t -- )
        solve();
    return 0;
}

C 小杜的签到

\[\sum_{i=1}^{n-1} ( a_{i+1} - a_i) = a_2-a_1+a_3-a_2+a_4-a_3+\cdots + a_n-a_{n-1}=a_n-a_1 \]

找一下最大值和最小值就好了

#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 = read() , mx = -1e9 , mn = 1e9;
    for( int x ; n ; n -- )
        x = read() , mx = max( mx , x ) , mn = min( mn , x );
    cout << mn - mx << " " << mx - mn << endl;
    return 0;
}

D 我超!原!

据说正解是贪心,但是我用了枚举答案的方法。

首先计算计算一下升级到x消耗的经验总和,然后特判一下特殊情况。我发现无论怎么组合,最终获得的经验总和一定是1000的倍数。所以找到大于经验总和且是1000倍数的最小值开始枚举,每次加1000直到第一次找到答案输出就好

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

const int A = 20000ll , B = 5000ll , C = 1000ll;

int32_t main() {
    int x , y , a , b , c , sum;
    cin >> x >> y >> a >> b >> c;
    if( x == 1 )
    {
        cout << "0\n";
        return 0;
    }
    sum = ( x - 1 ) * 1000ll + y * ( x - 1ll ) * ( x - 2ll )  / 2ll;
    if( a * A + b * B + c * C < sum ){
        cout << "QAQ\n";
        return 0;
    }
    for( int t = (sum / C + ( sum % C > 0 ) ) * C , i , j , k , p ; t ; t += C  )
    {
        p = t;
        i = min( a , p / A ) , p -= i * A;
        j = min( b , p / B ) , p -= j * B;
        if( c >= p / C ) {
            cout << t - sum << endl;
            return 0;
        }
    }
    return 0;
}

E 佳乐的迷宫

因为终点只有一个,所以从终点开始dfs找到所有的可以到达的点,然后判断哪些起点可以到达即可

#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 dx[] = { 0 , 0 , 1 , -1 };
const int dy[] = { 1 , -1 , 0 , 0 };
const int N = 1005;
int n , m , k , cnt;
string st[N];
bitset<N> vis[N];
vector< int > res;
pair<int,int> ex[N*N];

void dfs( int x , int y ){
    vis[x][y] = 1;
    for( int i = 0 , fx , fy ; i < 4 ; i ++ )
    {
        fx = x + dx[i] , fy = y + dy[i];
        if( fx < 0 || fy < 0 || fx >= n || fy >= m || st[fx][fy] == '#' || vis[fx][fy] ) continue;
        dfs( fx ,fy );
    }
}
int32_t main() {
    n = read() , m = read() , k = read();
    for( int i = 0 ; i < n ; i ++ )
        cin >> st[i];

    for( int i = 1 ; i <= k ; i ++ )
        ex[i].first = read() - 1 , ex[i].second = read() - 1;

    int x = read() , y = read();
    dfs( x - 1 , y - 1 );

    for( int i = 1 ; i <= k ; i ++ )
        if( vis[ex[i].first][ex[i].second] ) res.push_back(i);

    cout << res.size() << endl;
    for( auto it : res )
        cout << it <<  " ";
    return 0;
}

F 三四五

虽然不懂博弈,但是比赛的时候我写了个递推,发现如果取的范围是[1,k]那么k+1的倍数一定是先手必败,然后轮数是n/(k-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;
}

int32_t main() {
    int t = read();
    for( int n , m , k , a , b , c ; t ; t -- ){
        n = read() , m = read() , k = read();
        a = n / 4 , b = m / 5 , c = k / 6;
        if( a <= b && a <= c ){
            if( n % 4 == 0 )
                printf("(T-T)\n");
            else printf("(^-^)\n");
        }
        else if( b <= c && b <= a )
        {
            if( m % 5 == 0 )
                printf("(T-T)\n");
            else printf("(^-^)\n");
        }
        else {
            if( k % 6 == 0 )
                printf("(T-T)\n");
            else printf("(^-^)\n");
        }

    }
    return 0;
}

G 杰哥的疑问

丢在 map 里面记一下数,然后枚举key就好了

#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;
}

map< int , int > st;

int32_t main() {
    int n = read() ,  m = read() , cnt = 0;
    for( int x ; n ;n --  )
        x = read() , st[x] ++;
    for( auto [ k , v ] : st ){
        if( m - k < k ) break;
        if( m - k == k ) {
            cnt += v * ( v - 1 ) / 2;
            break;
        }
        if( st.find( m - k ) == st.end() ) continue;
        cnt += v * st[m-k];
    }
    cout << cnt << endl;
    return 0;
}

H 墨染的斯汀木

先把整个s1串转换成全部小写的字符串,然后根据s_0判断一下就好

#include<bits/stdc++.h>

using namespace std;

string s , p , t;

int32_t main() {
    cin >> s >> t;
    for( auto it : t )
        if( it >= 'A'&& it <= 'Z' ) p += it + 'a' - 'A' , p += it + 'a' - 'A';
        else p += it;
    for( int i = 0 , j = 0; i < s.size() ; i ++ , j ++ )
    {
        if( s[i] >= 'a' && s[i] <= 'z' )
            cout << s[i];
        else if( s[i] >= 'A' && s[i] <= 'Z' )
        {
            cout << s[i];
            j ++;
        }
        else if( s[i] == '?' )
            cout << p[j];
        else
        {
            cout << char( p[j] + 'A' - 'a' );
            j ++;
        }
    }
    return 0;
}

I , J Darling

两道题我用了相同的方法过掉了。如果要保证最优的情况那么异性边的端点一定是起点,并且端点到异性的距离就是1,然后从这些端点向外扩展,并且只扩展同性边,那么每次扩展到点到异性的距离就要加一。

对于这个过程的实现也非常的简单。首先读入边的时候只记录同性边,异性边的端点直接放到队列中,然后bfs一下就好,复杂度O(N)

#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 , t ;
int s[N] , vi[N] , dis[N];
vector<int> e[N] , nxt[2];
queue<int> q;

int32_t main() {
    n = read(), m = read(), t = read();
    for (int i = 1; i <= n; i++) s[i] = read();
    for (int i = 1; i <= n; i++) dis[i] = -1;
    for (int u, v; m; m--) {
        u = read(), v = read();
        if (s[u] != s[v])
            dis[u] = dis[v] = 1, q.push(u), q.push(v);
        else e[u].push_back(v), e[v].push_back(u); // 同性边
    }
    while (q.size()) {
        int u = q.front();
        q.pop();
        for (auto v: e[u]) {
            if (dis[v] != -1) continue;
            dis[v] = dis[u] + 1, q.push(v);
        }
    }
    for (int x; t; t--){
        x = read();
        printf("%d\n" , dis[x] );
    }
        return 0;
}

K 小杜返校记

这道题其实非常简单的,比赛的时候榜是歪的

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

double n , t;
double p[5][5];
string a , b;


int32_t main() {
    cin >> n >> t >> a >> b;
    for( int i = 1 ; i <= 3 ; i ++ )
        for( int j = 1 ; j <= 3 ; j ++ )
            cin >> p[i][j];
    int i , j;
    if( a == "First" ) i = 1;
    else if( a == "Business") i = 2;
    else i = 3;

    if( t >= 336 ) j = 0;
    else if( t >= 48 ) j = 1;
    else if( t >= 4 ) j = 2;
    else j = 3;
    printf("%.2lf\n" , n * ( 100 - p[i][j] ) / 100 );
    return 0;
}
posted @ 2022-07-09 13:40  PHarr  阅读(27)  评论(0编辑  收藏  举报