河南萌新联赛第四场补题

补了5道题

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

题目描述

小雷有一台特殊的电脑,这台电脑有一个mmm位的寄存器,能够存储一个mmm位的二进制数。换句话说,这台电脑可以存储一个从000到2m−12^m-12m−1之间的任何非负整数。
小雷还有一组nnn个非负整数的列表(中每一个数都严格小于2m2^m2m)。他想要找出这个列表中任意两个不同的数(下标不同就行),将它们放入电脑中进行同或运算后,得到的结果是所有可能的同或结果中最大的那个。
同或运算解释
同或运算(XNOR)是一种逻辑运算,它接受两个二进制位作为输入,并根据以下规则产生输出:
• 如果两个输入位相同,则输出为111;
• 如果两个输入位不同,则输出为000。
对于两个整数AAA和BBB,它们的同或结果是通过将AAA和BBB转换为二进制表示,然后对每个位进行同或运算得到的。

输入描述:

 
 
第一行输入 nnn mmm (2≤n≤200000,1≤m≤30)( 2\leq n\leq200000,1 \leq m \leq 30 )(2≤n≤200000,1≤m≤30)
接下来是n个整数a1,a2,a3……ana_1,a_2,a_3……a_na1​,a2​,a3​……an​ (保证aia_iai​严格小于2m2^m2m)

输出描述:

输出一个整数,这个整数是在这个数组任意两个数同或的最大值
示例1

输入

复制4 3 7 5 1 3
4 3
7
5
1
3

输出

复制5
5

说明

1在这台电脑中为001,3在这台电脑中为011,同或为101=5。

#include<bits/stdc++.h>
using namespace std;

int main() {
    int n, m;
    cin >> n >> m;
    
    vector<int> a(n);
    for (int i = 0; i < n; ++i) {
        cin >> a[i];
    }
    int minXOR = numeric_limits<int>::max();
    for (int i = 0; i < n; ++i) {
        for (int j = i + 1; j < n; ++j) {
            int xorResult = a[i] ^ a[j];
            if (xorResult < minXOR) {
                minXOR = xorResult;
            }
        }
    }
    int maxXNOR = (1 << m) - 1 - minXOR;
    cout << maxXNOR << endl;
    
    return 0;
}

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

题目描述

学校马上要举行校运会了,有众多志愿岗位需要被分配。但是负责老师临时有事现在由你来分配这些岗位。
现在有nnn个岗位,mmm位志愿者,每个岗位至少需要aia_iai​个志愿者,你需要将志愿者分配到岗位上,并且可以有志愿者空闲下来作预备。
请你给出可能的分配情况总数。

答案可能会很大,故需要对998,244,353998,244,353998,244,353取模。

注:所有岗位需求志愿者的总和不超过志愿者的总和且志愿者间无差别。

输入描述:

 

第一行输入两个字母nnn,mmm。
之后的一行输入nnn个被空格隔开的数,表示每个岗位至少需要的志愿者数。
1≤n≤1000,1≤ai≤m≤20001\leq n\leq1000,1\leq a_i \leq m \leq 20001≤n≤1000,1≤ai​≤m≤2000

输出描述:

一个数字,表示可能的分配情况总数。

示例1

输入

复制3 10 1 2 3

3 10
1 2 3

输出

复制35

35

#include <bits/stdc++.h>
using namespace std; 
typedef long long ll;
#define int long long
const ll mod = 998244353;
const int Max = 1e6 + 10;
ll fact[Max],ifact[Max];
ll n,m;
int sum = 0;
ll pow_mod(ll n,ll k)
{
    ll res=1;
    n=n%mod;
    while (k>0)
    {
        if (k&1)
            res=res*n%mod;
        n=n*n%mod;
        k>>=1;
    }
    return res;
}
void init()    
{
    fact[0]=ifact[0]=1;
    for (int i=1;i<Max;i++)
    {
        fact[i]=(fact[i-1]*i)%mod;
        ifact[i]=pow_mod(fact[i],mod-2);
    }
}
ll C(ll n, ll m)
{
    if (n<m||m<0) return 0;
    return (fact[n]*ifact[m]%mod)*ifact[n-m]%mod;
}
signed main()
{
    init();
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        int x;
        cin>>x;
        m-=x;
    }
    int ans = 1;
    for(int i=0;i<=m;i++)
    {
        for(int j = 1;j<=min(n,i);j++)
        {
            ans += C(n,j)%mod*C(i-1,j-1)%mod;
            ans %= mod;
        }
    }
    //int ans = C(m+n-1,n-1);
    cout<<ans<<endl;
    return 0;
}

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

题目描述

xiao hua 非常喜欢质数,ta想要知道在xxx和yyy之间有多少质数,并且这些质数形成的数组有多少个子区间ANDANDAND和为0。子区间 [l,r](1≤l≤r≤n)AND[l,r](1≤l≤r≤n)AND[l,r](1≤l≤r≤n)AND 和为 0,即a[l]a[l]a[l]至 a[r]a[r]a[r]中所有数进行ANDANDAND操作得到的结果为0。

与(AND)运算,运算规则:全一为一,有零为零。即只有两个操作数对应的二进制位都为1时,结果才为1,其他情况均为0(也可以说,只要有0,结果就为0)。

输入描述:

 

第一行给出一个数ttt
之后 ttt 行,每行会给出两个正整数 xxx和yyy。

1≤t≤1501 ≤ t ≤ 1501≤t≤150
2≤x≤​y≤1000000002 ≤ x ≤ ​y≤ 100 000 0002≤x≤​y≤100000000

输出描述:

 

每行输出两个整数aaa,bbb
aaa是xxx和yyy区间内的所有质数的数目
bbb是xxx和yyy区间内的所有质数形成的数组中有多少子区间and和为0

示例1

输入

复制3 2 3 2 4 2 5

3
2 3
2 4
2 5

输出

复制2 0 2 0 3 1

2 0
2 0
3 1

说明

 

第一个的质数有2,3

第二个的质数有2,3

第三个的质数有2,3,5,并且2,3,5的and和为0

备注:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<cstring>
#include<iomanip>
#include<unordered_set>
#include<queue>
#include<cmath>
#include<stack>
#define  FI(x) fixed<<setprecision(x)
using namespace std;
const int N = 100000010,M=10000010;
int prim[N];
bool st[N];
int cot;
void init()
{
    for(int i=2;i<=N;i++)
    {
        if(!st[i])
          prim[cot++]=i;
        for(int j=0;prim[j]<=N/i;j++)
        {
            st[prim[j]*i]=true;
            if(i%prim[j]==0)
              break;
        }
    }
}
int main()
{
    init();
    int t;
    cin>>t;
    while(t--)
    {
        int x,y;
        cin>>x>>y;
       // vector<int> A;
        int b[N];
        int k=0;
        for(int i=0;i<cot;i++)
        {
            if(prim[i]>=x&&prim[i]<=y)
            {
                //A.push_back(prim[i]);
                b[k++]=prim[i];
            }
            else if(prim[i]>y)
                break;
        }
        cout<<k<<" ";
        if(k==0)
        {
            cout<<0<<'\n';
            continue;
        }
        if(b[0]!=2)
        {
            cout<<0<<'\n';
            continue;
        }
        int m=0;
        int u=b[0];
        for(int i=1;i<k;i++)
        {
            u&=b[i];
            if(u==0)
            {
                m=k-i;
                break;
            }
        }
        cout<<m<<'\n';
    }
    return 0;
}

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

题目描述

    小明生活在一个名为running的国家,该国家由 nnn 个城市组成,编号从 111 到 nnn,还有 n−1n−1n−1 条双向道路连接着这些城市。从任何一个城市都可以到达另一个城市。每条道路都连接着两个城市 aaa 和 bbb 。这个国家是一个热爱跑步的国家,因此每天都会在一对城市 (u(u(u ,v)v)v) 之间举办一次马拉松,从 uuu 作为起点, vvv 作为终点,且 uuu != vvv 。小明需要用最短的路径到达从 uuu 到达 vvv(注意 (u(u(u ,v)v)v) 和 (v(v(v ,u)u)u) 是不同的马拉松)。
    令小明头疼的是该国家有两个城市 xxx 和 yyy,当小明经过 xxx 城市后又跑到 yyy 城市,那么该城市的警察就会阻止小明继续参加比赛。
    小明想知道在举办的所有马拉松路线中他会有多少个马拉松会在他参加时会被警察阻止。

输入描述:

第一行包含三个整数 nnn 、 xxx 和 yyy (2≤n≤3⋅105( 2 \leq n \leq 3⋅10 ^ 5(2≤n≤3⋅105 、 1≤x1 \leq x1≤x , y≤ny \leq ny≤n 、x≠y)x ≠ y )x​=y) --分别是城市数量、xxx 城市的编号和 yyy 城镇的编号。
接下来是 n−1n−1n−1 行,每行包含两个整数 aaa 和 bbb (1≤a( 1 \leq a(1≤a ,b≤nb \leq nb≤n , a≠b)a ≠ b )a​=b) ,描述了连接两个城镇 aaa 和 bbb 的道路。
可以保证的是,从每个城镇出发,我们都可以通过给定的道路到达城市中的其他城镇。也就是说,给定的城镇和道路地图是一棵树。

输出描述:

一个整数,表示小明在参加马拉松时会被警察阻止的数量 (u( u(u , v)v )v) 。

示例1

输入

复制5 1 5 1 2 2 3 3 4 4 5

5 1 5
1 2
2 3
3 4
4 5

输出

复制1

1

示例2

输入

复制5 1 5 1 2 1 3 1 4 1 5

5 1 5
1 2
1 3
1 4
1 5

输出

复制4

4

示例3

输入

复制5 2 3 1 2 1 3 2 4 1 5

5 2 3
1 2
1 3
2 4
1 5

输出

复制2

2

 #include <iostream>
#include <vector>
using namespace std;
const int N = 3e5 + 10;
vector<int> adj[N];
bool visited[N] ;
int n, u, v;
int dfs(int node, int k) {
    visited[node] = true;
    if (node == u || node == v) {
        k++;
    }
    int count = (k == 2) ? 1 : 0;
    for (int neighbor : adj[node]) {
        if (!visited[neighbor]) { 
            count += dfs(neighbor, k);
        }
    }
    return count;
}
int main() {
    cin >> n >> u >> v;
    for (int i = 0; i < n - 1; i++) {
        int a, b;
        cin >> a >> b;
        adj[a].push_back(b);
        adj[b].push_back(a);
    }
    fill(visited, visited +N, false);
    int first = dfs(u, 0);
    fill(visited, visited + N, false);
    int second = dfs(v, 0);
    cout << first * second << endl;
    return 0;
}

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

题目描述

神圣的帝皇禁军作为战锤40k中帝皇的亲卫,拥有无与伦比的力量。某一天,禁军们决定举办一场比赛,来活动一下他们的身体。每一个禁军都有一个能力值a[i]a[i]a[i](他们的实力可能相等),他们的比赛将会有两个神圣禁军作为参赛选手,但是禁军的power实在是太强大了,所以他们必须选择一个实力在他们两个人之间的神圣禁军来维护秩序。如果这个神圣禁军实力比参赛选手都强大或者比他们都弱小,那么两个选手都将会非常不满意,所以你必须保证维护秩序的禁军战士的实力在两个神圣禁军战士之间才可以。每三个神圣禁军只会进行一场比赛,要求每场比赛中aj∈[min(ai,ak),max(ai,ak)],(1≤i<j<k≤n)a_j \in \left [ min(a_i, a_k), max(a_i, a_k)\right ] , (1 \leq i < j < k \leq n)aj​∈[min(ai​,ak​),max(ai​,ak​)],(1≤i<j<k≤n)。请问聪明的你能计算出来一共能有多少场比赛吗?

输入描述:

 

第一行输入为TTT代表有多个测试点。(1≤T≤401 \leq T \leq 401≤T≤40)

接下来每两行一个测试点。

第一行输入为NNN,表示参与比赛的禁军数量。(3≤N≤20000)3 \leq N \leq 20000)3≤N≤20000)

第二行包含NNN个输入,aia_iai​表示第iii个禁军的能力值。(1≤ai≤1000001 \leq a_i \leq 1000001≤ai​≤100000)

输出描述:

 

每个测试点输出一个数,代表最多能有多少场比赛。

示例1

输入

复制1 6 8 4 11 14 13 1

1
6
8 4 11 14 13 1

输出

复制6

6

示例2

输入

复制2 4 12 14 6 10 11 1 14 3 2 11 9 4 9 4 14 12

2
4
12 14 6 10
11
1 14 3 2 11 9 4 9 4 14 12

输出

复制0 78

0
78

示例3

输入

复制1 7 5 4 8 4 6 1 10

1
7
5 4 8 4 6 1 10

输出

复制13

13

示例4

输入

复制1 4 1 1 1 1

1
4
1 1 1 1

输出

复制4

4

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define fo(i,l,r) for(int i=(l);i<=(r);++i)
#define fo(j,l,r) for(int j=(l);j<=(r);++j)
const int N = 1e5+10;
const int M = 20000+5;
int tr[N];
int l_low[M], l_up[M], r_low[M], r_up[M];
int l_cnt[M], r_cnt[M];
int lowbit(int x){
    return x & -x;
}
void update(int x, int k){
    while (x <= N){
        tr[x] += k;
        x += lowbit(x);
    }
}
int query(int x){
    int sum = 0;
    while (x){
        sum+=tr[x];
        x-=lowbit(x);
    }
    return sum;
}
void solve()
{
    int n, m, k;
    int ans = 0;
    cin >> n;
    vector<int> a(n+1);
    for (int i = 1; i<=n; i++){
        cin >> a[i];
    }
    for (int i = 1; i<=n; i++){
        l_low[i] = query(a[i]);
        l_up[i] = query(N)-query(a[i]-1);
        l_cnt[i] = query(a[i]) - query(a[i]-1);
        update(a[i], 1);
    }
    memset(tr, 0, sizeof(tr));
    for (int i=n; i>=1; i--){
        r_low[i] = query(a[i]);
        r_up[i] = query(N)-query(a[i]-1);
        r_cnt[i] = query(a[i])-query(a[i]-1);
        update(a[i], 1);
        ans += r_low[i] * l_up[i];
        ans += l_low[i] * r_up[i];
        ans -= l_cnt[i] * r_cnt[i];
    }
    cout << ans << endl;
}

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

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值