2026牛客寒假算法基础集训营2

锐评

总共10个题,赛时AC了5道题,进了前1000名

赛时AC顺序A > B > I > F > H

赛后AC顺序E 、J

难度:J > H > E > F > I > B > A


A

题目链接:https://ac.nowcoder.com/acm/contest/120562/A

思路:最大场次不能比最小场次超过1


代码:

/*Don’t cut corners, don’t over-rely on AI. Stay grounded, and keep challenging yourself with every single problem.*/
#include <bits/stdc++.h>
//当遇到感觉可以写但总是卡壳的题时,不妨先冷静下来仔细思考。
//当把题目真正读懂的时候,你已经写出来了一半。
//学习他人的做法也是一种提升。
//过程是很痛苦,但唯有坚持。
//输入报错可能是数组边界问题,看下循环条件关于索引的位置有没有放反
using namespace std;
using i64 = long long;
using u64 = unsigned long long;
constexpr i64 INF = 998244353;
constexpr int N = 300005;
constexpr double IP = 2.7182818;
constexpr i64 MAXN = 1E6 + 7;
constexpr i64 MOD = 1E9 + 7;

template<class T>
void solve(){
    int a, b, c, d;
    std::cin >> a >> b >> c;
    d = min({a, b, c});
    a -= d;
    b -= d;
    c -= d;
    if(a > 1 || b > 1 || c > 1){
        std::cout << "NO\n";
    }else{
        std::cout << "YES\n";
    }
}
int main(){
	ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
	int t=1;
	cin>>t;
	while(t--)
		solve<int>();
	return 0;
}

B

题目链接:https://ac.nowcoder.com/acm/contest/120562/B

思路:

对于每一个数我们想要留下他到最后,就把其他数与最大值比较消除,最后最大值与最大值共同竞争就会一起消掉,最大值为奇数说明最大值一定不会消完,那最大值就输出1,其他值只能为0,如果最大值是偶数个,说明最大值的数最后一定会两两消除,输出0,其他值可以通过最大值来消掉最后输出1.


代码:

/*Don’t cut corners, don’t over-rely on AI. Stay grounded, and keep challenging yourself with every single problem.*/
#include <bits/stdc++.h>
//当遇到感觉可以写但总是卡壳的题时,不妨先冷静下来仔细思考。
//当把题目真正读懂的时候,你已经写出来了一半。
//学习他人的做法也是一种提升。
//过程是很痛苦,但唯有坚持。
//输入报错可能是数组边界问题,看下循环条件关于索引的位置有没有放反
using namespace std;
using i64 = long long;
using u64 = unsigned long long;
constexpr i64 INF = 998244353;
constexpr int N = 300005;
constexpr double IP = 2.7182818;
constexpr i64 MAXN = 1E6 + 7;
constexpr i64 MOD = 1E9 + 7;

template<class T>
void solve(){
    int n;
    std::cin >> n;

    std::vector<int> a(n);
    for(auto &x : a) std::cin >> x;
    int mx = *max_element(a.begin(), a.end());
    int ans = 0;
    for(int i = 0;i < n; i++) if(a[i] == mx) ans ++;
    for(int i = 0;i < n; i++){
        if(a[i] < mx){
            if(ans & 1)
            std::cout << 0;
            else
            std::cout << 1;
        }else{
            if(ans & 1){
                std::cout << 1;
            }else{
                std::cout << 0;
            }
        }
    }
    std::cout << "\n";
}
int main(){
	ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
	int t=1;
	cin>>t;
	while(t--)
		solve<int>();
	return 0;
}

I

题目链接:https://ac.nowcoder.com/acm/contest/120562/I

思路:

1000...0001都是回文串

01111...11110也是回文串

所以我只需要看1的个数和0的个数只要大于1就一定能组成回文串


代码:

/*Don’t cut corners, don’t over-rely on AI. Stay grounded, and keep challenging yourself with every single problem.*/
#include <bits/stdc++.h>
//当遇到感觉可以写但总是卡壳的题时,不妨先冷静下来仔细思考。
//当把题目真正读懂的时候,你已经写出来了一半。
//学习他人的做法也是一种提升。
//过程是很痛苦,但唯有坚持。
//输入报错可能是数组边界问题,看下循环条件关于索引的位置有没有放反
using namespace std;
using i64 = long long;
using u64 = unsigned long long;
constexpr i64 INF = 998244353;
constexpr int N = 300005;
constexpr double IP = 2.7182818;
constexpr i64 MAXN = 1E6 + 7;
constexpr i64 MOD = 1E9 + 7;

template<class T>
void solve(){
    int n, m;
    std::cin >> n >> m;

    std::vector<string> s(n);
    for(int i = 0;i < n; i++) std::cin >> s[i];
    int ans = 0, cnt = 0;
    for(int i = 0;i < n; i++){
        for(int j = 0;j < m; j++){
            if(s[i][j] == '1') ans ++;
            else cnt ++;
        }
    }
    for(int i = 0;i < n; i++){
        for(int j = 0;j < m; j++){
            if(s[i][j] == '0' && cnt == 1){
                std::cout << 'N';
            }else if(s[i][j] == '1' && ans == 1){
                std::cout << 'N';
            }else{
                std::cout << 'Y';
            }
        }
        std::cout << "\n";
    }
}
int main(){
	ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
	int t=1;
	cin>>t;
	while(t--)
		solve<int>();
	return 0;
}

F

题目链接:https://ac.nowcoder.com/acm/contest/120562/F

思路:

要使x^y最小,x,y都是a的倍数,假设x = az, y = bz;x^y=(az)^(bz) = z*(a^b)>=z

因此我们找到异或值为z的就行,看z的二进制,x就在z的二进制后面拉等长位的0,eg:z:10001,x:1000100000

y就在x上加个z,y:1000110001,这两异或一定为z。


代码:

/*Don’t cut corners, don’t over-rely on AI. Stay grounded, and keep challenging yourself with every single problem.*/
#include <bits/stdc++.h>
//当遇到感觉可以写但总是卡壳的题时,不妨先冷静下来仔细思考。
//当把题目真正读懂的时候,你已经写出来了一半。
//学习他人的做法也是一种提升。
//过程是很痛苦,但唯有坚持。
//输入报错可能是数组边界问题,看下循环条件关于索引的位置有没有放反
using namespace std;
using i64 = long long;
using u64 = unsigned long long;
constexpr i64 INF = 998244353;
constexpr int N = 300005;
constexpr double IP = 2.7182818;
constexpr i64 MAXN = 1E6 + 7;
constexpr i64 MOD = 1E9 + 7;

template<class T>
void solve(){
    i64 n;
    std::cin >> n;

    i64 x = n;
    std::vector<int> a;
    while(x){
        a.insert(a.begin(), x % 2);
        x /= 2;
    }
    i64 ans = n, cnt = 0;
    int len = a.size();
    for(int i = 0;i < len; i++){
        ans = ans * 2;
    }
    cnt = ans + n;
    std::cout << ans << " " << cnt << "\n";
}
int main(){
	ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
	int t=1;
	cin>>t;
	while(t--)
		solve<int>();
	return 0;
}

H

题目链接:https://ac.nowcoder.com/acm/contest/120562/H

思路:

这里的权值指的是在给定区间[l, r]每次从[l,i]不同元素的个数的累加和。

我们用dp来转移,dp[0]先记录[1,n]的这个区间的权值,然后划分子区间子问题,删除从[1,n]逐个往前删,先删除1然后删除2在删除第三个数,然后我们先记录当前位置i所在的值x他后面有没有和他一样的数记录他的位置。有的话就等差递增(i, y), (y, n)就平级递增,没有的话全部等差递增,在前一个状态下减去,这里的dp指的是删除到第几个元素所产生的总数。


代码:

/*Don’t cut corners, don’t over-rely on AI. Stay grounded, and keep challenging yourself with every single problem.*/
#include <bits/stdc++.h>
//当遇到感觉可以写但总是卡壳的题时,不妨先冷静下来仔细思考。
//当把题目真正读懂的时候,你已经写出来了一半。
//学习他人的做法也是一种提升。
//过程是很痛苦,但唯有坚持。
//输入报错可能是数组边界问题,看下循环条件关于索引的位置有没有放反
using namespace std;
using i64 = long long;
using u64 = unsigned long long;
constexpr i64 INF = 998244353;
constexpr int N = 300005;
constexpr double IP = 2.7182818;
constexpr i64 MAXN = 1E6 + 7;
constexpr i64 MOD = 1E9 + 7;

template<class T>
void solve(){
    i64 n;
    std::cin >> n;

    std::vector<i64> a(n+1);
    for(int i = 1;i <= n; i++) std::cin >> a[i];
    std::vector<i64> dp(n+10), pre(n+10);
    i64 ans = 0, sum = 0;
    std::unordered_map<i64, i64> mp;
    for(int i = 1;i <= n; i++){
        if(!mp[a[i]]){
            ans ++;
        }
        mp[a[i]] = i;
        sum += ans;
        dp[0] += sum;
    }
    mp.clear();
    for(int i = n; i > 0; i--){
        pre[i] = mp[a[i]];
        mp[a[i]] = i;
    }

    for(int i = 1;i < n; i++){
        if(pre[i] == 0){
            i64 k = n - i + 1;
            dp[i] = dp[i-1] - k * (k + 1) / 2;
        }else{
            i64 k = pre[i] - 1 - i + 1;
            i64 s = n - pre[i] + 1;
            dp[i] = dp[i-1] - k * (k + 1) / 2 - s * k;
        }
    }
    i64 cost = 0;
    for(int i = 0;i < n; i++) cost += dp[i];
    std::cout << cost << "\n";
}
int main(){
	ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
	int t=1;
	cin>>t;
	while(t--)
		solve<int>();
	return 0;
}

E

题目链接:https://ac.nowcoder.com/acm/contest/120562/E

思路:构造场

n = 1
0
n = 2
10
00
n = 3
010
110
000
n = 4
1010
0010
1110
0000
n = 5
01010
11010
00010
11110
00000

代码:

/*Don’t cut corners, don’t over-rely on AI. Stay grounded, and keep challenging yourself with every single problem.*/
#include <bits/stdc++.h>
//当遇到感觉可以写但总是卡壳的题时,不妨先冷静下来仔细思考。
//当把题目真正读懂的时候,你已经写出来了一半。
//学习他人的做法也是一种提升。
//过程是很痛苦,但唯有坚持。
//输入报错可能是数组边界问题,看下循环条件关于索引的位置有没有放反
using namespace std;
using i64 = long long;
using u64 = unsigned long long;
constexpr i64 INF = 998244353;
constexpr int N = 300005;
constexpr double IP = 2.7182818;
constexpr i64 MAXN = 1E6 + 7;
constexpr i64 MOD = 1E9 + 7;

template<class T>
void solve(){
    /*
    n = 1
    0
    n = 2
    10
    00
    n = 3
    010
    110
    000
    n = 4
    1010
    0010
    1110
    0000
    n = 5
    01010
    11010
    00010
    11110
    00000
    n = 6
    101010
    001010
    111010
    000010
    111110
    000000
    */
    int n;
    std::cin >> n;

    std::vector<string> s(n);
    if(n & 1){
        for(int i = 0;i < n; i++){
            if(i & 1) s[0] += '1';
            else s[0] += '0';
        }
    }else{
        for(int i = 0;i < n; i++){
            if(i & 1) s[0] += '0';
            else s[0] += '1';
        }
    }
    for(int i = 1;i < n; i++){
        for(int j = 0;j <= i; j++){
            s[i] += s[0][i];
        }
        for(int j = i+1;j < n; j++){
            s[i] += s[0][j];
        }
    }
    for(int i = 0;i < n; i++){
        std::cout << s[i] << "\n";
    }
}
int main(){
	ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
	int t=1;
// 	cin>>t;
	while(t--)
		solve<int>();
	return 0;
}

J

题目链接:https://ac.nowcoder.com/acm/contest/120562/J

思路:

最短路问题:已知每个点相连的边数,我们就从最大开始遍历同时搜,对每个较低的点进行取最小值就可以了。


代码:

/*Don’t cut corners, don’t over-rely on AI. Stay grounded, and keep challenging yourself with every single problem.*/
#include <bits/stdc++.h>
//当遇到感觉可以写但总是卡壳的题时,不妨先冷静下来仔细思考。
//当把题目真正读懂的时候,你已经写出来了一半。
//学习他人的做法也是一种提升。
//过程是很痛苦,但唯有坚持。
//输入报错可能是数组边界问题,看下循环条件关于索引的位置有没有放反
using namespace std;
using i64 = long long;
using u64 = unsigned long long;
constexpr i64 INF = 998244353;
constexpr int N = 300005;
constexpr double IP = 2.7182818;
constexpr i64 MAXN = 1E6 + 7;
constexpr i64 MOD = 1E9 + 7;
struct point{
    int v;
    int step;
};
template<class T>
void solve(){
    int n, m;
    std::cin >> n >> m;

    std::vector<vector<int>> G(n+1);
    for(int i = 0;i < m; i++){
        int u, v;
        std::cin >> u >> v;
        G[u].push_back(v);
        G[v].push_back(u);
    }
    std::unordered_map<int, vector<int>> mp;
    for(int i = 1;i <= n; i++){
        int len = G[i].size();
        mp[len].push_back(i);
    }
    queue<point> q;
    std::vector<bool> vis(n+1);
    std::vector<int> ans(n+1, N);
    for(auto &[x, c] : mp){
        for(auto &u : c){
            q.push({u, 0});
            vis[u] = true;
        }
        while(!q.empty()){
            auto [a, b] = q.front();
            q.pop();
            for(auto &u : G[a]){
                if(vis[u]) continue;
                vis[u] = true;
                q.push({u, b + 1});
                int len = G[u].size();
                if(len < x) ans[u] = min(ans[u], b + 1);
            }
        }
        for(int i = 1;i <= n; i++) vis[i] = false;
    }
    for(int i = 1;i <= n; i++){
        std::cout << (ans[i] == N ? -1 : ans[i]) << " ";
    }
    std::cout << "\n";
}
int main(){
	ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
	int t=1;
	// cin>>t;
	while(t--)
		solve<int>();
	return 0;
}
全部评论

相关推荐

02-16 01:39
南昌大学 Java
重剑Ds:感觉不太可能 后端都减飞了 根本不缺人
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务