河南萌新联赛2024第(一)场:河南农业大学 A D F G H I K

A 造数

题目描述:

给定一个整数 𝑛 ,你可以进行以下三种操作

操作1: +1

操作2; +2

操作3: ×2

问最少需要多少次操作可以将 0 转为为 𝑛 。

解题思路

操作1,2,3。操作 3 的使 n 变小的更快。

AC代码

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
void solve()
{
	int n;cin>>n;
    int ans=0;
    while(n)
    {
        if(n==1||n==2)//操作1,操作2 的 逆过程
        {
            ans++;
            break;
        }
        if(n%2==1) //操作 1 的逆过程
        {
            n--;
            ans++;
        }
        else // 操作 3 的逆过程
        {
            n/=2;
            ans++;
        }
    }
    cout<<ans;
}
signed main()
{
	int t;
	t=1;
	while(t--)solve();
	return 0;
}

D 小蓝的二进制询问

题目描述

小蓝有 𝑡 组询问,每次给定两个数字 l,r 你需要计算出区间 [𝑙,𝑟] 中所有整数在二进制下1的个数之和。由于结果特别大,你只需要计算出结果模998244353之后的值即可。

解题思路

求出区间 [ 0 , x ] 之间的数的二进制下数的第 k 位是 1 时的所有情况

1.第 k 位前的数 为 k ^ 2 的倍数(周期 tl 的倍数),这时第 k 位后全为 0

  1. 第 k 位以及第 k 位后的数(为第 1 种情况的余数就是认定为 0 的数,实际不一定为 0 )如果大于周期,则加上大出的部分,否则不加

AC代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int mod=998244353;
int f(int x,int k)
{
    int y=1ll<<(k+1);// 2 的 k + 1 次幂,用于求出 x 的周期倍数
    int tl=y/2;// 周期(当第 k 位为 1 时,k 位之后为 0 1 的所有情况)
    x++;// 自增,用于后续判断 第 k 位 是否为 1 
    int res=(int)(x/y)*tl;// 计算出第一种情况
    int r=x%y; //求出第 k 位到 0 位的数
    r-=tl;
    if(r>0)res+=r;//计算第 2 种情况
    return res%mod;
}
void solve()
{
    int l,r;cin>>l>>r;
    int ans=0;
    for(int i=61;i>=0;i--)
    {
        int t=(f(r,i)-f(l-1,i))%mod;// 第 i 位为 1 时,[0 ,r] 与 [0,l-1] 的情况差
        ans=(ans+t)%mod;
    }
    cout<<ans<<'\n';
}
signed main()
{
    int t;cin>>t;
    while(t--)solve();
    return 0;
}

F 两难抉择新编

题目描述

现在有长度为 n n n 的数组 a a a,你可以在两种操作中选择一种 进行最多一次操作。

  • 操作1:

选择一个数 i i i ( 1 ≤ i ≤ n ) (1\leq i\leq n) (1≤i≤n) 使得 a i : = a i + x a_i:=a_i+x ai:=ai+x, x x x 可以是 [ 1 , ⌊ n / i ⌋ ] [1,\lfloor n/i \rfloor] [1,⌊n/i⌋] 范围内任意正整数( ⌊ ⌋ \lfloor\rfloor ⌊⌋ 表示向下取整 )。

  • 操作2:

选择一个数 i i i ( 1 ≤ i ≤ n ) (1\leq i\leq n) (1≤i≤n) 使得 a i : = a i × x a_i:=a_i \times x ai:=ai×x, x x x 可以是 [ 1 , ⌊ n / i ⌋ ] [1,\lfloor n/i \rfloor] [1,⌊n/i⌋] 范围内任意正整数。

请问进行操作后,最大的数组异或和是多少?

数组异或和:数组 a a a 中 a 1 ⊕ a 2 ⊕ a 3 . . . ⊕ a n a_1\oplus a_2 \oplus a_3 ... \oplus a_n a1⊕a2⊕a3...⊕an的值, ⊕ \oplus ⊕ 表示异或。

解题思路

直接模拟所有情况,理解异或( ^ )的自逆

AC代码

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 PII pair<int,int>
#define fi first
#define se second
const int N=2e5+10;
int a[N];
void solve()
{
	int n;cin>>n;
    int sum=0;
    for(int i=0;i<n;i++)
    {
        cin>>a[i];
        if(i==0)
        {
            sum=a[i];
            continue;
        }
        sum=sum^a[i];
    }
    int ans=0;
    for(int i=0;i<n;i++)
    {
        int t=sum^a[i];
        for(int j=1;j<=n/(i+1);j++)
        {
            int x=t^(j+a[i]),y=t^(j*a[i]);
            ans=max(ans,max(x,y));
        }
    }
    cout<<ans;
}
signed main()
{
	int t;
//	cin>>t;
	t=1;
	while(t--)solve();
	return 0;
}

G 旅途的终点

题目描绘

在某大陆上面有 n n n 个国家,作为旅行者兼冒险家的你想以一种既定的路线(即从1到 n n n )去畅游这 n n n 个国家,但由于这 n n n 个国家并不太平,因此每到一个国家你都需要消耗 a i a_i ai 点的生命力来帮助这个国家重回往日的安宁然后再进行畅游。不过天生拥有神力的你却有 k k k 次释放神力的机会来帮助这个国家恢复安宁,且释放神力时不消耗任何生命力。你在旅行前拥有 m m m 点的生命力,若你在旅途中不幸用完全部的生命力,则便会回到你诞生的地方陷入沉睡。现在请问你最多可以畅游多少个国家。注意:若在当前国家消耗完生命力则意味着你并没有畅游该国家。

输入

输入包含 2 行。

第一行三个正整数 n , m , k ( 1 ≤ n ≤ 2 × 1 0 5 , 1 ≤ m ≤ 1 0 18 , 0 ≤ k ≤ 2 × 1 0 5 ) n,m,k(1≤n≤2\times10^5,1≤m≤10^{18},0≤k≤2\times10^5) n,m,k(1≤n≤2×105,1≤m≤1018,0≤k≤2×105) ,分别代表国家的个数,你拥有的初始生命力,你可以释放神力的次数。

第二行包含 n n n 个正整数,第 i i i 个正整数 a i ( 1 ≤ a i ≤ 1 0 18 ) a_i (1≤a_i≤10^{18}) ai(1≤ai≤1018) 代表你不释放神力帮助第 i i i 个国家需要消耗的生命力的大小。

输出

输出包含一行,共一个数,表示你能畅游的国家的个数。

解题思路

逆贪心,用优先队列 ,需要释放技能时,每次消化当前位置到首位的最大值。

AC代码

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 PII pair<int,int>
#define fi first
#define se second
const int N=2e5+10;
void solve()
{
    priority_queue<int>q;
	int n,m,k;cin>>n>>m>>k;
    int ans=0;
    int i;
    for(i=0;i<n;i++)
    {
        int x;cin>>x;
        m-=x;
        q.push(x);
        if(m<=0&&k)
        {
            k--;
            m+=q.top();
            q.pop();
        }
        if(m<=0)break;
    }
    cout<<i;
}
signed main()
{
	int t;
//	cin>>t;
	t=1;
	while(t--)solve();
	return 0;
}

H 两难抉择

题目描述

现在有长度为 n n n 的数组 a a a,你可以在两种操作中选择一种 进行最多一次操作。

  • 操作1:

选择一个数 i i i ( 1 ≤ i ≤ n ) (1\leq i\leq n) (1≤i≤n) 使得 a i : = a i + x a_i:=a_i+x ai:=ai+x, x x x 可以是 [ 1 , n ] [1,n] [1,n] 范围内任意正整数。

  • 操作2:

选择一个数 i i i ( 1 ≤ i ≤ n ) (1\leq i\leq n) (1≤i≤n) 使得 a i : = a i × x a_i:=a_i \times x ai:=ai×x, x x x 可以是 [ 1 , n ] [1,n] [1,n] 范围内任意正整数。

请问进行操作后,最大的数组总和是多少?

输入

输入包含两行.

第一行一个正整数 n n n ( 1 ≤ n ≤ 2 × 1 0 5 ) (1\leq n\leq 2 \times 10^5) (1≤n≤2×105) 表示数组 a a a 的长度。

第二行 n n n 个正整数 a i a_i ai ( 1 ≤ a i ≤ 1 0 9 ) (1\leq a_i \leq10^9) (1≤ai≤109) 表示数组 a a a 的元素。

输出

输出包含一行一个整数,表示最大的数组总和。

解题思路

变化最大的 a i a_i ai ,使数组和最大

AC代码

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 PII pair<int,int>
#define fi first
#define se second
const int N=2e5+10;
int a[N];
void solve()
{
	int n;cin>>n;
    int ma=-1,sum=0;
    for(int i=0;i<n;i++)
    {
        cin>>a[i];
        sum+=a[i];
        ma=max(a[i],ma);
    }
    sum-=ma;
    if((sum+ma*n)>=(sum+ma+n))cout<<sum+ma*n;
    else    cout<<sum+ma+n;
}
signed main()
{
	int t;
	t=1;
	while(t--)solve();
	return 0;
}

I 除法移位

题目描述

现在有长度为 n n n 的数组 a a a,式子 S S S 定义为 S = a 1 ÷ a 2 ÷ a 3 . . . ÷ a n S=a_1\div a_2\div a_3...\div a_n S=a1÷a2÷a3...÷an,最多对数组 a a a 进行 t t t 次循环右移 操作**。

**

请问,进行第几次操作时使得 S S S 最大?若存在多种答案,请输出最小值。

循环右移:一次操作使数组从 a 1 , a 2 , a 3 , . . . , a n a_1,a_2,a_3,...,a_n a1,a2,a3,...,an 形式转换为 a n , a 1 , a 2 , . . . , a n − 1 a_n,a_1,a_2,...,a_{n-1} an,a1,a2,...,an−1 形式。

输入

输入包含两行.

第一行一个正整数 n , t n,t n,t ( 1 ≤ n ≤ 2 × 1 0 5 , 0 ≤ t ≤ 1 0 9 ) (1\leq n\leq 2\times10^5,0\leq t\leq 10^9) (1≤n≤2×105,0≤t≤109) 表示数组 a a a 的长度和最多的操作次数。

第二行 n n n 个正整数 a i a_i ai ( 1 ≤ a i ≤ 1 0 9 ) (1\leq a_i \leq10^9) (1≤ai≤109) 表示数组 a a a 的元素。

输出

输出包含一行一个整数,表示使得 S S S 最大的最小操作次数。

解题思路

尽可能将大数移到首位

AC代码

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 PII pair<int,int>
#define fi first
#define se second
const int N=2e5+10;
int a[N];
map<int , int>mp;
vector<int> q;
map<int,int>v;
void solve()
{
	int n,t;cin>>n>>t;
    int ma=-1;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
        mp[a[i]]=i;
        v[a[i]]++;
        if(v[a[i]]==1)
        {
            q.push_back(a[i]);
        }
    }
    sort(q.begin(),q.end());
    int ans=0;
    for(int i=q.size()-1;i>=0;i--)
    {
        int x=q[i];
        int y=mp[x];
        if((n-y+1)<=t)
        {
            ans=n-y+1;
            break;
        }
    }
    if(ans==n)ans=0;
    cout<<ans;
}
signed main()
{
	int t;
//	cin>>t;
	t=1;
	while(t--)solve();
	return 0;
}

K 图上计数(Easy)

题目描述

E a s y Easy Easy 版本和 H a r d Hard Hard 版本唯一的区别是 H a r d Hard Hard 版本删除的是桥,而 E a s y Easy Easy 版本删除的是任意边。

你有一张 n n n 个点 m m m 条边的无向图,你有无数次删除操作来删除任意条边以获得若干个联通块。定义联通块的大小为其所包含点个数。定义这个图的代价是:你有任意次操作,每次操作合并两个联通块,合并后联通块大小为二者之和,最后剩下两个联通块大小的乘积为此图的代价,若只有一个则代价为0。你需要最大化此图代价。

输入

第一行包含两个整数 n n n 和 m m m ,图中顶点的数量和边的数量。

接下来的每 m m m 行包含两个整数 u u u 和 v v v ,表示图中顶点 u u u 和 v v v 之间有一条无向边。

( 0 < n ≤ 1 0 6 ) \left ( 0< n\leq 10^{6} \right ) (0<n≤106)

( 0 ≤ m ≤ 1 0 6 ) \left ( 0\leq m\leq 10^{6} \right ) (0≤m≤106)

( 0 < u , v ≤ n ) \left ( 0< u,v\leq n \right ) (0<u,v≤n)

输出

输出一个整数表示最大代价。

解题思路

删除所有边,可能任意组合

AC代码

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 PII pair<int,int>
#define fi first
#define se second
void solve()
{
	int n;cin>>n;
    cout<<(n/2)*(n-n/2);
}
signed main()
{
	int t;
//	cin>>t;
	t=1;
	while(t--)solve();
	return 0;
}
相关推荐
m0_6312704024 分钟前
标准C++(二)
开发语言·c++·算法
沫刃起27 分钟前
Codeforces Round 972 (Div. 2) C. Lazy Narek
数据结构·c++·算法
GZM8888881 小时前
配置VS Code以进行C/C++编程:深入探讨与实操指南
c++
martian6651 小时前
学懂C++(六十):C++ 11、C++ 14、C++ 17、C++ 20新特性大总结(万字详解大全)
开发语言·c++·c++20
小灰灰爱代码2 小时前
C++——判断year是不是闰年。
数据结构·c++·算法
小灰灰爱代码3 小时前
C++——求3个数中最大的数(分别考虑整数、双精度数、长整数数的情况),用函数重载方法。
数据结构·c++·算法
爱coding的橙子4 小时前
CCF-CSP认证考试准备第十七天
数据结构·c++·算法
程序猿阿伟5 小时前
《C++移动语义:解锁复杂数据结构的高效之道》
数据结构·c++·html
594h26 小时前
PAT 甲级 1002题
数据结构·c++·算法
小周的C语言学习笔记7 小时前
鹏哥C语言33---循环语句 for
c语言·c++·算法