河南农业大学萌新赛(一)补题

总共12个题目,做了其中的A,F,G,H,I,K,现对其对中的B,C,D重做,其余几题太难了。。。。。。而且时间上也来不及了。

链接:登录—专业IT笔试面试备考平台_牛客网
来源:牛客网

题目描述

某天朵拉穿越到了一个冒险世界中,该世界共有 nnn 个冒险关卡,朵拉可以选择任意一个关卡作为起始关卡,若朵拉选择了 iii 号关卡,则完成该关卡的冒险后,朵拉可以选择回到原来的世界即冒险结束,或选择传送到第 aia_iai​ 号关卡,(其中对于任意一个 iii 号关卡,其 aia_iai​ 号关卡是固定的。)由于朵拉喜欢探险,因此她想向你请教她最多可以探险多少个不同的关卡。(其中,对于关卡 i、ji、ji、j,当且仅当 i=ji=ji=j 时,我们才认为 iii 和 jjj 是同一个关卡。)

输入描述:

输入包含 2 行。
第一行一个正整数 n(1≤n≤105)n(1≤n≤10^5)n(1≤n≤105),代表关卡的数量。
第二行 nnn 个正整数,其中第 iii 个正整数 ai(1≤ai≤n)a_i(1≤a_i≤n)ai​(1≤ai​≤n) 代表完成第 iii 个关卡后会被传送到的关卡。(若 i≠ji≠ji​=j,则可能存在 ai=aja_i=a_jai​=aj​)

输出描述:

输出包含一行一个整数,表示朵拉最多可以探险的关卡的数量。

示例1

输入

复制5 1 2 4 5 3

5
1 2 4 5 3

输出

复制3

3

说明

当朵拉选择从3、4、5中的任意一个关卡开始时,探险的关卡种类数量最多,为3个,分别为{3,4,5}。

示例2

输入

复制5 2 3 4 5 1

5
2 3 4 5 1

输出

复制5

5

说明

可知,不管朵拉选择从哪一个关卡开始,她都能探险这5个关卡。

代码如下

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int idx = 1, h[N];
int w , s = 0;
int lhl[N];
int gdf[N];
void lxp(int x) {
     
    if (h[x] == -1) {
        h[x] = 0;
        w++;
        gdf[x]=0;
        lxp(lhl[x]);
        
        }
    if(x==lhl[x]) 
        {
            gdf[x]=0;
     return;
    }
    return;
}
int main() {
    int a, b;
    cin >> a;
    memset(h, -1, sizeof h);
    memset(gdf, 1, sizeof gdf);
    for (int i = 1; i <= a; i++) {
        cin >> lhl[i];
    }
    for (int i = 1; i <= a; i++) {
       
        if(gdf[i]){
        memset(h, -1, sizeof h);
        w=0;
            lxp(i);
        s = max(s, w);
        }
    }
    cout << s << endl;
    return 0;
}

核心:运用深搜找出其中的最大的环就可以了

链接:登录—专业IT笔试面试备考平台_牛客网
来源:牛客网
 

题目描述

在某幼儿园中共有 nnn 个小朋友,该幼儿园的老师为这 nnn 个小朋友准备了 nnn 份不一样的零食大礼包。每个小朋友只能选择一个,但老师并不知道小朋友们喜欢什么类型的零食大礼包,因此,老师让小朋友们分别说出了他们喜欢的零食大礼包都有哪些,老师希望能根据小朋友们的叙述来让所有的小朋友们都能吃到他们喜欢的零食。若并非所有的小朋友都能吃到自己满意的零食,请问老师最少还应购买多少份零食大礼包来保证所有的小朋友都能吃到自己满意的零食。题目保证任意一个小朋友都会喜欢这 nnn 种大礼包中的至少一种。

输入描述:

输入包含 n+1n+1n+1 行。
第一行一个正整数 nnn (1≤n≤500)(1≤n≤500)(1≤n≤500),表示该幼儿园小朋友的数量。
接下来 nnn 行,每行先给出一个正整数 kik_iki​(1≤ki≤n)(1≤k_i≤n)(1≤ki​≤n),代表第 iii 个小朋友喜欢的零食大礼包的种类数量,然后给出 kik_iki​ 个正整数,第 jjj(1≤j≤ki)(1 \leq j \leq k_i)(1≤j≤ki​) 个正整数 aj(1≤aj≤n)a_j(1≤a_j≤n)aj​(1≤aj​≤n) 代表第 iii 个小朋友喜欢的零食大礼包的编号。(保证每行的 kik_iki​ 个正整数不重复,且 ∑i=1nki≤2×105∑_{i=1}^{n} k_i≤2\times10^5∑i=1n​ki​≤2×105 )

输出描述:

若所有的小朋友都能吃到自己喜欢的零食,则输出 “Yes”(不带双引号);
反之,则在第一行输出“No”(不带双引号),并在第二行输出老师还应购买的零食大礼包的最少的个数。

示例1

输入

复制3 2 1 2 1 3 3 1 2 3

3
2 1 2
1 3
3 1 2 3

输出

复制Yes

Yes

说明

根据题目描述和样例,老师可以选择给第一个小朋友1号大礼包,给第二个小朋友3号大礼包,给第三个小朋友2号大礼包。这样可以保证每个小朋友可以吃到自己喜欢的零食。

示例2

输入

复制3 2 1 2 1 1 2 1 2

3
2 1 2
1 1
2 1 2

输出

复制No 1

No
1

代码如下:

#include<bits/stdc++.h>
using namespace std;
const int N = 505; 
const int M = 1000000;
int n,m,k,a,b,ans;
struct edge{int v,ne;}e[M];
int h[N],idx;
int vis[N],match[N];
void add(int a,int b){
    e[++idx]={b,h[a]};
    h[a]=idx;
}
bool dfs(int u){
    for(int i=h[u];i;i=e[i].ne){
        int v=e[i].v;
        if(vis[v]) continue;
        vis[v]=1;
        if(!match[v]||dfs(match[v])){
            match[v]=u;
            return 1;
        }
    }
    return 0;
}
int main()
{
    cin>>n;
    for(int i=0;i<n;i++)
    {
        cin>>m;
        while(m--)
        {
            cin>>k;
            add(i+1,k);
        }
    }
    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;
         cout<<n-ans<<endl;}
    return 0;
    
}

核心:匈牙利算法

链接:登录—专业IT笔试面试备考平台_牛客网
来源:牛客网
 

题目描述

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

输入描述:

第一行输入一个正整数 ttt 表示询问组数。

接下来每行两个整数 l,rl,rl,r 。

(1≤t≤105)\left ( 1\leq t\leq 10^{5} \right )(1≤t≤105)

(1≤l≤r≤1018)\left ( 1\leq l\leq r\leq 10^{18} \right )(1≤l≤r≤1018)

输出描述:

每行输出一个整数表示答案。

示例1

输入

复制1 1 5

1
1 5

输出

复制7

7

说明

1~5的二进制下分别是1 10 11 100 101共有7个1
#include <bits/stdc++.h>
using namespace std;

const long long p = 998244353;

// 计算从1到x的所有整数在第k位上1的个数
long long Calc(long long x, int k) {
    long long d = (x+1)/ (1ll << (k + 1));
    long long R = d * (1ll << k) % p;
    if ((x+1) % (1ll << (k + 1)) >= (1ll << k))
        R += (x+1) % (1ll << (k + 1)) - (1ll << k);
    return R % p;
}

int main() {
    int T;
    cin >> T;
    while (T--) {
        long long l, r;
        cin >> l >> r;
        long long Ans = 0;
        for (int i = 0; i < 62; ++i) {
            Ans = (Ans + Calc(r, i) - Calc(l - 1, i)) % p;
            if (Ans < 0)
                Ans += p;
        }
        cout << Ans << endl;
    }
    return 0;
}

核心:位运算

  • 12
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值