1. 程式人生 > 實用技巧 >牛客小白月賽30題解(部分)

牛客小白月賽30題解(部分)

牛客小白月賽30題解(部分)

A.黑白邊

考點:並查集、最小生成樹

根據題可以看出,就是一道最小生成樹的裸模板題

程式碼:

#include <iostream>
#include <cstdio>
#include <algorithm>

using namespace std;

const int N = 2e5+10, INF = 0x3f3f3f3f;

int n, m;
int p[N];

struct Edge
{
    int a, b, w;
    
    bool operator < (const Edge &t) const
    {
        return w < t.w;
    }
}edges[N];
    
int find(int x)
{
    if(p[x] != x) p[x] = find(p[x]);
    return p[x];
}
    
int kruskal()
{
    sort(edges, edges + m);
    
    for(int i = 1; i <= n; i++) p[i] = i;
    
    int res = 0, cnt = 0;
    for(int i = 0; i < m; i++)
    {
        int a = edges[i].a, b = edges[i].b, c = edges[i].w;
        
        a = find(a), b = find(b);
        if(a != b)
        {
            res += c;
            cnt++;
            p[a] = b;
        }
    }
    
    if(cnt < n-1) return INF;
    else return res;
}

int main()
{
    cin >> n >> m;
    for(int i = 0; i < m; i++) scanf("%d%d%d", &edges[i].a, &edges[i].b, &edges[i].w);
    
    int t = kruskal();
    
    if(t == INF) cout << -1 << endl;
    else cout << t << endl;
    
    return 0;
}

B.最好的寶石

待補。。。。。。

C.滑板上樓梯

考點:貪心、數學

根據題意:要使次數最少,就要儘可能多走3步;3+1為一組,除一下,然後特判最後剩餘步數是否為3即可

程式碼:

#include <iostream>

using namespace std;

int main()
{
    long long n;
    cin >> n;

    cout << n / 4 * 2 + ((n % 4) == 3 ? 1 : n % 4) << endl;
    
    return 0;
}

D.GCD

考點:篩法求質數

分析題目可得:如果我們把1~n所有的質數和1全部放入子集,則任意兩個數的 gcd(x, y)

均等於1
故要使題意成立,需滿足兩個條件:
1、1~n必須有合數
2、滿足1的條件下,k的最小值為 質數+2(包含1和1個合數)
解法:求出1~n所有的質數cnt,如果不等於n-1,則k = cnt+2;否則不存在輸出-1

程式碼:

#include <iostream>

using namespace std;

const int N = 1e5+10;

int cnt, primes[N];
bool st[N];

void get_primes(int n)
{
    for(int i = 2; i <= n; i++)
    {
        if(!st[i]) primes[cnt++] = i;
        for(int j = 0; primes[j] <= n / i; j++)
        {
            st[primes[j] * i] = true;
            if(i % primes[j] == 0) break;
        }
    }
}
int main()
{
    int n;
    cin >> n;
    
    get_primes(n);
    
    if(cnt + 1 == n) cout << -1 << endl;
    else cout << cnt + 2 << endl;
    
    return 0;
}

E.牛牛的加法

考點:高精度加法(大數加法)、模擬

高精度加法模板題

程式碼:

#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;

vector<int> A, B;

vector<int> add(vector<int> A, vector<int> B)
{
	vector<int> C;
	for(int i = 0; i < A.size() || i < B.size(); i++)
	{
		int t = 0;
		if(i < A.size()) t += A[i];
		if(i < B.size()) t += B[i];
		C.push_back(t % 10);
	}
	
	return C;
}

int main()
{
	string a, b;
	cin >> a >> b;
	
	for(int i = a.size() - 1; ~i; i--) A.push_back(a[i] - '0');
	for(int i = b.size() - 1; ~i; i--) B.push_back(b[i] - '0');
	
	vector<int> C = add(A, B);
	while(C.size() > 1 && C.back() == 0) C.pop_back();
	
	for(int i = C.size() - 1; ~i; i--) cout << C[i];
 
	return 0;
 } 

F.石子合併

考點:貪心

貪心,每次選最大的和其相鄰的某一個,記錄總和,最後加上max*(n-2)即可

#include <iostream>
#include <cstdio>
#include <algorithm>

using namespace std;

typedef long long ll;

int n;
ll ans, m;

int main()
{
    cin >> n;
    for(int i = 0; i < n; i++) 
    {
        ll a;
        scanf("%lld", &a);
        ans += a;
        m = max(m, a);
    }
    
    cout << ans + m * (n - 2) << endl;
    
    return 0;
}

G.滑板比賽

待補。。。。。。

H.第k小

待補。。。。。。

I.區間異或

待補。。。。。。

J.小遊戲

考點:動態規劃

程式碼:

#include <iostream>
#include <cstdio>
#include <algorithm>

using namespace std;

const int N = 2e5+10;

int n, cnt[N];
long long f[N];

int main()
{
    cin >> n;
    
    for(int i = 1; i <= n; i++)
    {
        int a;
        scanf("%d", &a);
        cnt[a]++;
    }
    
    long long ans = 0;
    for(int i = 0; i <= 2e5; i++)
    {
        f[i] = max(f[max(0,i - 1)], f[max(0, i - 2)] + i * cnt[i]);
        ans = max(ans, f[i]);
    }
    
    cout << ans << endl;
        
    return 0;
}