河南萌新联赛第六场补题

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

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 524288K,其他语言1048576K
64bit IO Format: %lld

题目描述

这是一个16进制的世界,比如522的16进制是20A。

在5月22日那天,有人送给Bob一些月饼,每个月饼有饱食度和幸福度两个属性。

现在Bob有nnn个月饼,对于每个月饼iii,饱食度为viv_ivi​,幸福度为wiw_iwi​。

Bob现在有mmm饱食度,意味着他吃的月饼的饱食度之和不大于mmm。

但是由于Bob身处16进制的世界,他吃的月饼的幸福度之和必须是16的倍数。

请帮Bob算一下他最多吃的月饼的数量。

输入描述:

第一行输入两个整数n, mn,\ mn, m

接下来nnn行分别输入vi, wiv_i, \ w_ivi​, wi​表示第iii个月饼的饱食度和幸福度。

输入数据保证1≤n⋅m≤1051 \leq n \cdot m \leq 10^51≤n⋅m≤105, 1≤vi≤1051 \leq v_i \leq 10^51≤vi​≤105, 1≤wi≤1091 \leq w_i \leq 10^91≤wi​≤109。

输出描述:

一个整数,表示Bob最多能吃的月饼数量

示例1

输入

复制2 5 2 16 3 15

2 5
2 16
3 15

输出

复制1

1

#include <iostream>
#include <cstdio>
using namespace std;
const int inf=1e9;
const int maxn=1e5+5;
const int mod=16;

int n,m;
int dp[maxn][20];//饱食度 幸福度 

int main(){
    cin.tie(0)->sync_with_stdio(false);
    cin>>n>>m;
    for(int i=0;i<=m;i++)
        for(int j=0;j<mod;j++)
            dp[i][j]=-inf;
    dp[0][0]=0;
    
    for(int _=1,v,w;_<=n;_++){
        cin>>v>>w;
        w%=mod;
        for(int i=m-v;i>=0;i--)
            for(int j=0;j<16;j++)
                dp[i+v][(j+w)%mod]=max(dp[i+v][(j+w)%mod],dp[i][j]+1);
    }
    int ans=0;
    for(int i=0;i<=m;i++)ans=max(ans,dp[i][0]);
    cout<<ans<<endl;
    return 0;
}
 

 

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

时间限制:C/C++ 2秒,其他语言4秒
空间限制:C/C++ 524288K,其他语言1048576K
64bit IO Format: %lld

题目描述

在扑克牌中有种玩法叫做24点,目标是用给定的四张牌通过基本的数学运算(加、减、乘、除)得到24。24点的玩法规则如下:

1. 准备一副扑克牌,去掉大小王,使用 `A,2,3,4,5,6,7,8,9,10,J,Q,K` 分别表示 `1,2,3,4,5,6,7,8,9,10,11,12,13`。每种各四张,共52张牌。
2. 每次从这些牌中任意取出四张牌。
3. 使用这四张牌的数字,通过加法、减法、乘法和除法运算,最终得到24。(除法是正常的数学除法,即有可能出现除不尽的情况,比如 1÷3=131\div 3=\dfrac131÷3=31​)
4. 每张牌只能使用一次,可以任意调换数字的顺序,可以使用任意的括号来改变运算顺序。
5. 玩家需要找到至少一种解决方案。如果无法用四张牌得到24点,则说明没有解。

现在需要你判断某种情况下是否有解。

输入描述:

第一行一个正整数 TTT (1≤T≤1000)(1\le T\le 1000)(1≤T≤1000),表示数据的组数。

接下来 TTT 行,每行四个字符串,表示取出的四张牌的点数,输入的扑克牌点数只会出现 `A,2,3,4,5,6,7,8,9,10,J,Q,K`。

输出描述:

输出一行一个字符串,如果有解输出 `YES`,无解输出 `NO`

示例1

输入

复制5 8 2 2 A 5 J 10 4 9 K A A A 10 10 A 10 8 9 7

5
8 2 2 A
5 J 10 4
9 K A A
A 10 10 A
10 8 9 7

输出

复制YES YES YES NO YES

YES
YES
YES
NO
YES

#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <map>
#include <ctime>
using namespace std;
const double eps=1e-9;

int T;
bool ck[15][15][15][15];

bool merge(vector<double> &a,int idx,int opt){//是否可以成功合并,可以则合并 
    if(a.end()-a.begin()<idx+1)return false;
    if(opt==3 && a[idx+1]==0)return false;//除0了
    
    if(opt==0)a[idx]+=a[idx+1];
    else if(opt==1)a[idx]-=a[idx+1];
    else if(opt==2)a[idx]*=a[idx+1];
    else if(opt==3)a[idx]/=a[idx+1];
    
    a.erase(a.begin()+idx+1);
    return true;
}
double compute(vector<int> t,int order,int optr){//od顺序,opt运算符 
    vector<double> a;
    for(int i=0;i<4;i++)
        a.push_back(t[i]);
    int idx,opt;
    idx=order%3;order/=3;
    opt=optr%4;optr/=4;
    if(!merge(a,idx,opt))return -1;
    idx=order;
    opt=optr%4;optr/=4;
    if(!merge(a,idx,opt))return -1;
    idx=0;
    opt=optr%4;optr/=4;
    if(!merge(a,idx,opt))return -1;
    return a[0];
}
void check(vector<int> a){
    auto &flag=ck[a[0]][a[1]][a[2]][a[3]];
    do{
        for(int od=0;od<6;od++)//这里枚举运算顺序,用两位3进制数代替,不过最高位只能取得到0,1
            for(int opt=0;opt<64;opt++)
                if(abs((compute(a,od,opt)-24))<=eps){
                    flag=true;
                    return;
                }
    }while(next_permutation(a.begin(),a.end()));
    flag=false;
    return;
}

map<string,int> mp;

int main(){
    cin.tie(0)->sync_with_stdio(false);
    
    mp["A"]=1;
    mp["2"]=2;
    mp["3"]=3;
    mp["4"]=4;
    mp["5"]=5;
    mp["6"]=6;
    mp["7"]=7;
    mp["8"]=8;
    mp["9"]=9;
    mp["10"]=10;
    mp["J"]=11;
    mp["Q"]=12;
    mp["K"]=13;
    
    for(int a=1;a<=13;a++)
        for(int b=a;b<=13;b++)
            for(int c=b;c<=13;c++)
                for(int d=c;d<=13;d++)
                    check(vector<int>{a,b,c,d});
    
    cin>>T;
    
    int t[4];
    string tmp;
    while(T--){
        for(int i=0;i<4;i++){
            cin>>tmp;
            t[i]=mp[tmp];
        }
        sort(t,t+4);
        cout<<((ck[t[0]][t[1]][t[2]][t[3]])?"YES":"NO")<<"\n";
    }
    
    return 0; 
}
 

 

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

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 524288K,其他语言1048576K
64bit IO Format: %lld

题目描述

*"正义之枪从不打背身"*。小x最近迷上了无畏契约,钟爱"正义"这把武器。可他使用该武器有一条原则:不击杀(打不中)背对自己的敌人。小x实力强大,对于所有直面自己的敌人都能一击毙命。

在一次游戏中。小x面前有nnn个点位,从左往右序依次为1,2,3,……,n1,2,3,……,n1,2,3,……,n。每个点位上都有一个敌人。

每个敌人 要么正面朝向小x,要么背面朝向小x。

小x实力强大,打算强迫这n个敌人玩mmm轮小游戏之后再对每个人开枪。

游戏规则如下:

在第iii轮小游戏中,依次执行以下所有操作:

* 序号为[1,i][1,i][1,i]的点位上的敌人位置改变。改变规则为: 从1,2,3,……,i1,2,3,……,i1,2,3,……,i 变为i,i−1,……,3,2,1i,i-1,……,3,2,1i,i−1,……,3,2,1(原来位于i号位置的敌人更换到1号位置,位于i-1号位置的敌人更换到2号位置……)

* 序号为[1,i][1,i][1,i]的点位上的敌人原地旋转180°。

所有小游戏过后,小x想知道。目前在每个点位的敌人是否被击败。

输入描述:

第一行输入两个整数 n,mn,mn,m

接下来一行输入一个仅由'P'和‘B'组成的字符串s。si=′P′s_i='P'si​=′P′ 表示第i个点位的敌人当前正面对小x。si=′B′s_i='B'si​=′B′表示第i个点位的敌人当前正背对小x。

对于所有数据保证:1≤m≤n≤2×1061\le m \le n\le 2\times 10^61≤m≤n≤2×106。∣s∣=n|s|=n∣s∣=n

输出描述:

输出一行n个整数。对于第i个数,如果目前位于第i个点位的敌人被击败则输出1,否则输出0。

示例1

输入

复制3 3 PPP

3 3
PPP

输出

复制0 0 1

0 0 1

cin>>n>>m;
vector<int> a(n+1);
for(int i=1;i<=n;i++)a[i]=i;
for(int i=1;i<=m;i++){
    for(int j=1;j<=i/2;j++)
    swap(a[j],a[i-j+1]);
    for(int j=1;j<=i;j++)vis[a[j]]^=1;
    
    printf("%2d:",i);
    for(int j=1;j<=i;j++)
        cout<<a[j]<<" ";
    cout<<endl;
    printf("  :");
    for(int j=1;j<=i;j++)
        cout<<(vis[a[j]]?"*":"-")<<" ";
    cout<<endl;
}
 

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

时间限制:C/C++ 2秒,其他语言4秒
空间限制:C/C++ 524288K,其他语言1048576K
64bit IO Format: %lld

题目描述

koala设计了一个程序,首先他写了一个暴力算法,但是在他写完之后受到电脑病毒的影响而失忆。好在他的源代码和题面数据范围保留了下来(数据范围在输入描述中已经给出),但是现在仍然无法通过这个题目。由于电脑病毒的影响,题面已经消失,现在他希望你基于源代码做出优化来解决这道题。

C++代码:

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

// 链表结构体定义
typedef struct node {
    int id;
    struct node *next;
} *pNode, Node;

// 循环链表头节点
pNode head;

// 按顺序删除的前n-1个节点的id构成的列表
vector<int> ans;

int main() {
    // n个节点,判断值k
    int n, k;
    cin >> n >> k;

    // 构造包含n个节点的循环链表
    head = (pNode)malloc(sizeof(Node));
    pNode now = head;
    for (int i = 1; i <= n; ++i) {
        pNode a = (pNode)malloc(sizeof(Node));
        a->id = i;
        now->next = a;
        now = now->next;
    }
    now->next = head->next;

    // pc为计数器
    int pc = 0;
    now = head;

    // 当前节点的上一个节点
    pNode last = nullptr;

    // 程序执行到链表只剩下最后一个节点为止
    while (n > 1) {
        pc++;
        last = now;
        now = now->next;
        // 当计数器pc = k时从循环链表中删除当前节点,并把被删除的节点的id添加到答案列表ans中
        if (pc == k) {
            last->next = now->next;
            n--;
            pc = 0;
            ans.push_back(now->id);
        }
    }

    // 输出最终答案
    for (auto id : ans) {
        cout << id << ' ';
    }

    return 0;
}


 

输入描述:

一行包合两个整数 n,k(2≤n≤3∗105,1≤k≤3∗105)n, k (2 \le n \le 3 * 10^5 , 1 \le k \le 3 * 10^5)n,k(2≤n≤3∗105,1≤k≤3∗105)

输出描述:

根据题意输出答案

示例1

输入

复制10 3

10 3

输出

复制3 6 9 2 7 1 8 5 10

3 6 9 2 7 1 8 5 10

#include <iostream>
#include <cstdio>
using namespace std;
const int maxn=3e5+5;

int n,k;

struct segement_tree{
    #define ls (p<<1)
    #define rs (p<<1|1)
    
    int tr[maxn<<3],n;
    
    void push_up(int p){
        tr[p]=tr[ls]+tr[rs];
    }
    void build(int p,int l,int r){
        if(l==r){
            tr[p]=1;
            return;
        }
        int mid=(l+r)>>1;
        build(ls,l,mid);
        build(rs,mid+1,r);
        push_up(p);
    }
    void build(int _n){
        n=_n;
        build(1,1,_n);
    }
    void print(int p,int l,int r){
        printf("%d[%d,%d]:%d\n",p,l,r,tr[p]);
        if(l==r){
            
            return;
        }
        int mid=(l+r)>>1;
        print(ls,l,mid);
        print(rs,mid+1,r);
    }
    void print(){
        print(1,1,n);
        cout<<endl;
    }
    
    void mdy(int p,int l,int r,int id){
        if(l==r){
            tr[p]=0;
            return;
        }
        int mid=(l+r)>>1;
        if(id<=mid)mdy(ls,l,mid,id);
        else mdy(rs,mid+1,r,id);
        push_up(p);
    }
    int count(int p,int l,int r,int L,int R){//区间[L,R]的剩余人数 
        if(L<=l && r<=R){
            return tr[p];
        }
        int mid=(l+r)>>1,ans=0;
        if(mid>=L)ans+=count(ls,l,mid,L,R);
        if(mid<R)ans+=count(rs,mid+1,r,L,R);
        return ans;
    }
    int search(int l,int r,int x){//范围[l,r]二分找第x个人的编号 
        int L=l,mid;
        while(l<r){
            mid=(l+r)>>1;
            if(count(1,1,n,L,mid)>=x)r=mid;
            else l=mid+1;
        }
        return l;
    }
    int q(int id,int x){//从id开始向下报x次数
        int idx;
        x=(x-1)%count(1,1,n,1,n)+1;//先转整轮,剩下的次数是不够一轮报数的
        if(count(1,1,n,id,n)>=x)idx=search(id,n,x);//区间[id,n]的剩余人数可以报完
        else {//不能报完,回到[1,id]区间继续报数
            x-=count(1,1,n,id,n);
            idx=search(1,id,x);
        }
        mdy(1,1,n,idx);//删人
        return idx;
    }
    
    #undef ls
    #undef rs    
}tr;

int main(){
    cin.tie(0)->sync_with_stdio(false);
    cin>>n>>k;
    tr.build(n);
    for(int i=1,idx=1;i<n;i++){
//        tr.print();
        idx=tr.q(idx,k);
        cout<<idx<<" ";
    }
    return 0;
}
 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值