2026牛客寒假算法基础集训营2(A B I F E H)

这场打的非常差......

A 比赛安排

思路:

题目还是很简洁的,三种比赛进行分配,任意连续的 3 场比赛的类型互不相同,,最后只能其中一种比赛类型或者两种比赛类型多一场,所以最多比赛场次和最少比赛场次的差值不能超过1。
代码:

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
#define int long long
#define endl '\n'
void solve()
{
    int a,b,c;
    cin>>a>>b>>c;
    int ma=max(a,max(b,c));
    int mi=min(a,min(b,c));
    if(ma-mi<=1)cout<<"YES"<<endl;
    else cout<<"NO"<<endl;
}
signed main()
{
    int t;
    cin>>t;
    while(t--)
    {
        solve();
    }
}

B NCPC

思路:

给定n个整数,每次可以选定两个整数,若两个数字不等,留下较大值,否则全部删除,问对于每个整数能否是最后剩下的数字。如果最大的数是奇数个的话,那么其余所有的数都不可能剩下,相反的,如果最大的数个数是偶数个的话,其余所有的数都有可能留下。
代码:

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
#define x first
#define y second
#define endl "\n"
const int N=2e5+5;
int a[N];
void solve()
{
    int n;
    cin>>n;
    int ma=0;
    map<int,int> cnt;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
        ma=max(a[i],ma);
        cnt[a[i]]++;
    }
    bool flag;
    if(cnt[ma]%2)flag=true;
    else flag=false;
    for(int i=1;i<=n;i++)
    {
        if(flag)
        {
            if(a[i]==ma)cout<<"1";
            else cout<<"0";
        }else{
            if(a[i]==ma)cout<<"0";
            else cout<<"1";
        }
    }
    cout<<endl;
}
signed main(){
	IOS
	int t;
	cin>>t;
	//int t=1;
	while(t--)
	{
		solve();
	}
}

I 01 回文

思路:

这个题的话统计 0/1 个数,只要大于等于 2 就是有可能的,注意下超时问题。
代码:

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
#define endl "\n"
int dx[4]={-1,0,1,0};
int dy[4]={0,1,0,-1};
void solve()
{
    int n,m;
    cin>>n>>m;
    vector<vector<char>> ch(n,vector<char>(m));
    int cnt0=0,cnt1=0;
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<m;j++)
        {
            cin>>ch[i][j];
            if(ch[i][j]=='0')cnt0++;
            else cnt1++;
        }
    }
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<m;j++)
        {
            if(ch[i][j]=='1')
            {
                if(cnt1>1)cout<<"Y";
                else cout<<"N";
            }else{
                if(cnt0>1)cout<<"Y";
                else cout<<"N";
            }
        }
        cout<<endl;
    }
}
signed main(){
	IOS;
	int t;
	cin>>t;
	//int t=1;
	while(t--)
	{
		solve();
	}
}

F x?y?n!

题意:

gcd⁡(x,y)=n 条件下最小化 x⊕yx \oplus yx⊕y。
思路:

根据 x⊕y≥∣x−y∣x \oplus y \ge |x-y|x⊕y≥∣x−y∣,gcd⁡(x,y)=n,可知 ∣x−y∣|x-y|∣x−y∣ 至少是 n 的一倍,所以 x⊕y≥nx \oplus y \ge nx⊕y≥n。
x=a∗n,y=b∗nx=a*n,y=b*nx=a∗n,y=b∗n,所以 gcd(a,b)=1

XOR 最小意味着两个数的二进制表示越相同。n 是理论最小下界。让 x,y 在所有高位完全相同,只在最低若干位制造差异,且差异值正好是 n。

我们令 a=2k,b=2k+1a=2^k,b=2^k+1a=2k,b=2k+1 此时 gcd(a,b)=1。此时的 x=n∗2k=n<<kx=n*2^k=n<<kx=n∗2k=n<<k (PS: 二进制知识点这里一个数字乘一个 2 就相当于把二进制表示中每位的位权加一,也就是相当于在二进制表示后面补了个 0 所以等同于将 n 的所有二进制位向左移动 k 个位置,右边空出的位补 0。)

此时 x⊕y=(n≪k)⊕((n≪k)+n)x⊕y=(n≪k)⊕((n≪k)+n)x⊕y=(n≪k)⊕((n≪k)+n),可以看成 A⊕(A+B)=BA⊕(A+B)=BA⊕(A+B)=B。

两边同时异或 B 可以得到 A⊕(A+B)⊕B=0A⊕(A+B)⊕B=0A⊕(A+B)⊕B=0 即 (A⊕B)⊕(A+B)=0(A⊕B)⊕(A+B)=0(A⊕B)⊕(A+B)=0,可得 (A⊕B)=(A+B)(A⊕B)=(A+B)(A⊕B)=(A+B)。

二进制加法和异或的关系 A+B=(A⊕B)+2∗(A&B)A+B=(A⊕B)+2*(A\And B)A+B=(A⊕B)+2∗(A&B)

在二进制下,异或是不进位的加法,A&B 是产生进位的位。

当 A & B=0A \And  B=0A & B=0 时,没有进位。此时 A+B=(A⊕B)A+B=(A⊕B)A+B=(A⊕B)。所以 (n≪k)&n=0(n≪k)\And n=0(n≪k)&n=0。

接下来我们去找满足 (n≪k)&n=0(n≪k)\And n=0(n≪k)&n=0 的 k。
代码:

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
#define x first
#define y second
#define endl "\n"
void solve()
{
    int n;
    cin>>n;
    int a=0,b=0,k=n;
    for(int i=1;i<=31;i++)
    {
        k<<=1;
        if((k&n)==0)
        {
            a=k,b=k+n;
            break;
        }
    }
    cout<<a<<" "<<b<<endl;
}
signed main(){
	IOS
	int t;
	cin>>t;
	//int t=1;
	while(t--)
	{
		solve();
	}
}

E 01矩阵

思路:

只能说很玄幻。😇可以根据 2 的构造往后推一下。
代码:

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
#define int long long
#define endl '\n'
void solve()
{
    int n;
    cin>>n;
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<n;j++)
        {
            cout<<min(i,j)%2;
        }
        cout<<endl;
    }
}
signed main()
{
    int t=1;
    while(t--)
    {
        solve();
    }
}

H 权值计算

思路:

读懂题是第一步,伪代码是在计算一个数组中每个前缀中不同元素个数的和。,然后我们需要计算一个数组的每个子数组的权值之和。

我们用第二个样例来找找规律。数组为{1,1,4,5,1,4},我们来计算每个子数组的贡献。

l 的范围是1 ,n,r 的范围是l, n

l\r 1 2 3 4 5 6
1 1 1 2 3 3 3
2 1 2 3 3 3
3 1 2 3 3
4 1 2 3
5 1 2
6 1
列和 1 2 5 9 12 15

可以发现如果 ai之前没有出现过,相较于上一列会增加 i 的贡献,否则增加 i−posi-posi−pos 的贡献(pos 为上次出现的位置)。

所以对于一个位置 i,它对答案的贡献为 ∑l=1ig(l,i)∗(n−i+1)\\sum\^{i}_{l=1}g(l,i)*(n-i+1)∑l=1ig(l,i)∗(n−i+1)。
g(l, i) 表示从 li 这段区间中不同元素的个数。

所以 ans=∑i=1n∑l=1ig(l,i)∗(n−i+1)ans=\sum^{n}_{i=1}\\sum\^{i}_{l=1}g(l,i)*(n-i+1)ans=∑i=1n∑l=1ig(l,i)∗(n−i+1)。

令 sumi=∑l=1ig(l,i)sumi=\sum^{i}_{l=1}g(l,i)sumi=∑l=1ig(l,i)
代码:

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
#define x first
#define y second
#define endl "\n"
void solve()
{
    int n;
    cin>>n;
    vector<int> a(n+1);
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
    }
    map<int,int>m;//记录每个值最近一次出现的位置
    int ans=0;
    int sum=0;
    for(int i=1;i<=n;i++)
    {
        int last=0;
        last=m[a[i]];
        m[a[i]]=i;
        sum+=i-last;
        ans+=sum*(n-i+1);
    }
    cout<<ans<<endl;
}
signed main(){
	IOS
	int t;
	cin>>t;
	//int t=1;
	while(t--)
	{
		solve();
	}
}
相关推荐
学计算机的计算基2 分钟前
回溯算法下篇:四道经典题讲透约束剪枝、原地标记、预计算与状态压缩
java·笔记·算法
霸道流氓气质29 分钟前
SpringBoot中实现告警判定算法-位报警与模拟量阈值-技术详解
spring boot·算法·jquery
行者全栈架构师31 分钟前
混元 Hy3 Agent 实战:季度报告 3 小时变 40 分钟
算法·架构·代码规范
兰令水1 小时前
hot100【acm版】【2026.7.21打卡-java版本】
java·开发语言·算法·leetcode·面试
好好沉淀1 小时前
主键选择(自增 vs UUID vs 雪花算法)
java·算法
退休倒计时2 小时前
【每日一题】LeetCode 131. 分割回文串 TypeScript
算法·leetcode·typescript
小白说大模型2 小时前
AI Agent 调试实战:链路追踪、Prompt 可视化与异常定位的系统方法
java·人工智能·python·算法·prompt
梅梅绵绵冰2 小时前
算法题-矩阵
数据结构·算法·矩阵
atunet2 小时前
关于从哈希冲突看缓存设计的实践与权衡7
算法
GuWenyue11 小时前
传统Agent工具两大痛点!300行代码落地MCP跨语言工具,彻底解耦LLM与工具
前端·人工智能·算法