河南萌新联赛2024第(一)场:河南农业大学

A.造数

倒着贪心,小于等于2时方案加1后输出,反之如果是奇数得先-1,再除2,偶数就直接除2

#include<bits/stdc++.h>
#define endl '\n'
#define mk make_pair
#define int long long
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int N = 3e5+10;
const int mod = 998244353;
int n,m,k;

void sovle(){
    int num=0;
    cin>>n;if(n==0) {
        cout<<0<<endl;
        return;
    }
    while(n){
        if(n<=2){
            cout<<num+1<<endl;
            return;
        }else if(n%2){
            n--;
        }else{
            n/=2;
        }
        num++;
    }
}

signed main()
{	
    ios::sync_with_stdio(false), cin.tie(0),cout.tie(0); 
    int t = 1; 
    //cin>>t;
    while (t--){
        sovle();
    }

    return 0;
}

B.爱探险的朵拉

有点难,补不补待定吧,没找到合适的题解

C.有大家喜欢的零食吗

二分图最大匹配的板子题,之前没学过...匈牙利算法秒了

#include<bits/stdc++.h>
#define endl '\n'
#define mk make_pair
#define int long long
using namespace std;
typedef pair<int, int> PII;
const int N = 1e6+10;
int n,m,k;
bool vis[505];
int match[505];
vector<int>a[505];

bool dfs(int u){
    for(int ed:a[u]){
        if(vis[ed]) continue;
        vis[ed]=1;
        if(!match[ed]||dfs(match[ed])){
            match[ed]=u;
            return 1;
        }
    }
    return 0;
}

void sovle(){
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>m;
        for(int j=1;j<=m;j++){
            cin>>k;
            a[i].push_back(k);
        }
    }
    int ans=0;
    for(int i=1;i<=n;i++){
        memset(vis,0,sizeof(vis));
        if(dfs(i)) ans++;
    }if(ans==n) cout<<"Yes"<<endl;
    else cout<<"No"<<endl<<n-ans<<endl;
}

signed main()
{	
    ios::sync_with_stdio(false), cin.tie(0),cout.tie(0); 
    int t = 1; 
    //cin>>t;
    while (t--){
        sovle();
    }

    return 0;
}

D.小蓝的二进制询问

按位拆分后发现,每个位上是有循环节的,具体是从当前位的值-1开始循环的,循环的周期为2的当前位次(1是第1位,2是第2位,4是第3位......)次方,每个周期拥有的1的个数就是周期大小的一半。然后具体要算l到r区间的值,我们可以用前缀和S[r]-S[l-1]。

#include<bits/stdc++.h>
#define endl '\n'
#define mk make_pair
#define int long long
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int N = 1e5+10;
const int mod = 998244353;
int n,m,k;


int check(int xx){
    int num=0,vl=1,qu=2,bei=1;
    while(vl<=xx){
        int x=xx-vl+1;
        num+=x/qu*bei;num%=mod;
        num+=min(qu/2,x%qu);num%=mod;
        vl*=2;qu*=2;bei*=2;
    }return num;
}

void sovle(){
    int x,y;
    cin>>x>>y;
    cout<<check(y)-check(x-1)<<endl;
}

signed main()
{	
    ios::sync_with_stdio(false), cin.tie(0),cout.tie(0); 
    int t = 1; 
    cin>>t;
    while (t--){
        sovle();
    }

    return 0;
}

F.两难抉择新编

将所有能选的数的总和算出来发现,最坏的情况下也不超过1e7,所以这题暴力枚举就可以过

一个数异或它本身等于0,任何数异或0都等于它本身

#include<bits/stdc++.h>
#define endl '\n'
#define mk make_pair
#define int long long
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int N = 2e5+10;
const int mod = 998244353;
int n,m,k;
int a[N];

void sovle(){
    cin>>n;
    int num=0;
    for(int i=1;i<=n;i++){
        cin>>a[i];  num^=a[i];
    }
    int max1=-1;
    for(int i=1;i<=n;i++){
        int sum=num^a[i];
        for(int j=1;j<=n/i;j++){
            max1=max(sum^(a[i]+j),max1);
            max1=max(sum^(a[i]*j),max1);
        }
    }
    cout<<max1<<endl;
}

signed main()
{	
    ios::sync_with_stdio(false), cin.tie(0),cout.tie(0); 
    int t = 1; 
    //cin>>t;
    while (t--){
        sovle();
    }

    return 0;
}

G.旅途的终点

如果在第x个国家,即使采取最优策略也无法畅游,那么后面的国家也是无法畅游的,说明在某个位置开始答案就变得不可取,显然答案具有单调性,所以我们二分畅游的国家个数。对于二分出的个数,我们在这些国家中选最大的k个使用神力,如果这样还不能全部畅游选中的国家,那么就是取大了,反之就是取小了。

#include<bits/stdc++.h>
#define endl '\n'
#define mk make_pair
#define int long long
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int N = 2e5+10;
const int mod = 998244353;
int n,m,k;
int a[N];

bool ok(int x){
    vector<int>q(x);
    for(int i=0;i<x;i++){
        q[i]=a[i];
    }sort(q.begin(),q.end());
    int f=m;
    for(int i=1;i<=x-k;i++){
        f-=q[i];
        if(f<=0) return 0;
    }
    return 1;
}

void sovle(){
    cin>>n>>m>>k;
    for(int i=0;i<n;i++) cin>>a[i];
    int l=0,r=n,ans=0;
    while(l<=r){
        int mid=(l+r)>>1;
        if(ok(mid)){
            ans=mid;
            l=mid+1;
        }else r=mid-1;
    }if(ans>n) ans=n;
    cout<<ans<<endl;
}

signed main()
{	
    ios::sync_with_stdio(false), cin.tie(0),cout.tie(0); 
    int t = 1; 
    //cin>>t;
    while (t--){
        sovle();
    }

    return 0;
}

H.两难抉择

操作一情况唯一,操作二最优在最大的数✖️n

#include<bits/stdc++.h>
#define endl '\n'
#define mk make_pair
#define int long long
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int N = 3e5+10;
const int mod = 998244353;
int n,m,k;

void sovle(){
    cin>>n;
    int sum=n,num=0,max1=0;
    vector<int>a(n),b(n);
    for(int i=0;i<n;i++){
        cin>>a[i];
        sum+=a[i];
        b[i]=a[i];
        num+=b[i];
        max1=max(max1,b[i]);
    }num-=max1;num+=n*max1;
    cout<<max(num,sum)<<endl;
}

signed main()
{	
    ios::sync_with_stdio(false), cin.tie(0),cout.tie(0); 
    int t = 1; 
    //cin>>t;
    while (t--){
        sovle();
    }

    return 0;
}

I.除法移位

式子可以化成a1➗(a2✖️a3✖️a4···),要使值最大,则要使值最大,则让a1取可取范围内的最大值,可取范围就是max(0,n-m+1)到n,特别的如果a1就是最大值,则不用操作

#include<bits/stdc++.h>
#define endl '\n'
#define mk make_pair
#define int long long
using namespace std;
typedef pair<int, int> PII;
const int N = 1e6+10;
int n,m,k;


void sovle(){
    cin>>n>>m;
    vector<int>a(n);
    int max1=0,u=0;
    for(int i=0;i<n;i++){
        cin>>a[i];
    }
    for(int i=n-1;i>=max((long long)0,n-m);i--){
        if(a[i]>max1){
            max1=a[i];
            u=n-i;
            if(u==n) u=0; 
        }
    }
    cout<<u<<endl;
}

signed main()
{	
    ios::sync_with_stdio(false), cin.tie(0),cout.tie(0); 
    int t = 1; 
    //cin>>t;
    while (t--){
        sovle();
    }

    return 0;
}

K.图上计数(Easy)

蒽,红温题,甚至用上了并查集,后来发现读假了。

可以把边全部删除,再任意地合成,那么只要n不等于1,我们总是可以合成n/2和(n/2+n%2)使得乘积最大

#include<bits/stdc++.h>
#define endl '\n'
#define mk make_pair
#define int long long
using namespace std;
typedef pair<int, int> PII;
const int N = 1e6+10;
int n,m,k;

void sovle(){
    cin>>n>>m;
    cout<<n/2*(n/2+n%2);
}

signed main()
{	
    ios::sync_with_stdio(false), cin.tie(0),cout.tie(0); 
    int t = 1; 
    //cin>>t;
    while (t--){
        sovle();
    }

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值