链接:登录—专业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;
}