六题
C 16进制世界
链接:登录—专业IT笔试面试备考平台_牛客网
来源:牛客网
题目描述
这是一个16进制的世界,比如522的16进制是20A。
在5月22日那天,有人送给Bob一些月饼,每个月饼有饱食度和幸福度两个属性。
现在Bob有n个月饼,对于每个月饼iii,饱食度为vi,幸福度为wi。
Bob现在有m饱食度,意味着他吃的月饼的饱食度之和不大于m。
但是由于Bob身处16进制的世界,他吃的月饼的幸福度之和必须是16的倍数。
请帮Bob算一下他最多吃的月饼的数量。
输入描述:
第一行输入两个整数n, m 接下来n行分别输入vi, wi表示第i个月饼的饱食度和幸福度。 输入数据保证1≤n⋅m≤105。
输出描述:
一个整数,表示Bob最多能吃的月饼数量
示例1
输入
2 5 2 16 3 15
输出
1
思路
代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n, m;
int dp[100005][16];//dp[k1][k2]表示当前月饼数 k2表示 mod 16的值
signed main() {
cin >> n >> m;
vector<int> m1(n);
vector<int> m2(n);
for (int i = 0; i < n; ++i) {
cin >> m1[i] >> m2[i];
}
memset(dp, -1, sizeof(dp));
dp[0][0] = 0;
for (int i=0;i<n;i++) {
int v = m1[i];
int w = m2[i];
for (int j = m; j >= v; --j) {
for (int k = 0; k < 16; ++k) { //遍历0--15 各个位置的dp
if (dp[j - v][k] != -1) {
int h = (k + w) % 16;
//现在跟上一个比较 上一个要加一个
dp[j][h] = max(dp[j][h], dp[j - v][k] + 1);
}
}
}
}
int res = 0;
for (int j = 0; j <= m; ++j) {
res = max(res, dp[j][0]);//找到 k2为0也就是mod 16=0 的数的max月饼数
}
cout << res << endl;
return 0;
}
G 等公交车
链接:登录—专业IT笔试面试备考平台_牛客网
来源:牛客网
题目描述
小G和朋友约好了时间出去玩,他选择坐公交车去找对方。
早早的便来到了公交站牌处开始了等公交车,但公交车却迟迟不来,终于在他濒临爆发的时候,公交车终于缓缓开来。开心的和朋友会合后,他们便开始了一天的玩乐。回到家后,小G还是对于等公交车耿耿于怀,现已知每天都会发出m辆公交车,在手机上它可以查出这m辆公交车的发车时刻第ti 分钟,并且他还知道所有的站点信息,总共有n个公交车站点,第 i 个站点距离发车点的距离为di 米。已知公交车的速度为1米/分钟,发车点和所有的站点都在一条直线上, 每次公交车从发车点出发后,依次经过每个站点。他想知道能否设计一个程序,当每次一个乘客在某个时刻时到达某个站点时,可以直接告诉他需要等待的时间?
输入描述:
第一行两个个正整数,表示n,m. 第二行n个正整数,表示n个站点距离发车点的距离di.(数据保证di递增) 第三行m个正整数,表示m辆公交车的发车时刻ti.(数据保证ti递增) 第四行一个正整数Q,表示接下来的询问个数。
接下来Q行,每行两个正整数t,x,表示该乘客在时刻t时来到了x号站点。
对于100%的数据,1≤n,m,q≤105,1≤li,ti≤2×109
输出描述:
Q行,每行一个整数表示需要等待的时间,若该乘客任何公交车都无法乘上,请输出`TNT`
示例1
输入
2 3 2 4 1 3 5 5 3 1 4 1 5 1 8 2 10 2
输出
0 1 0 1 TNT
思路
二分查找
代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,m,d[100005],t[100005],q;
signed main() {
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>d[i];
}
for(int i=1;i<=m;i++){
cin>>t[i];
}
cin>>q;
int y=0;
while(q--){
int tt,x;cin>>tt>>x;
int nt=tt-d[x];
auto y=lower_bound(t+1,t+m+1,nt);
if(y==m+1+t){
cout<<"TNT"<<endl;
}
else cout<<*y-nt<<endl;
}
return 0;
}
H 24点
链接:登录—专业IT笔试面试备考平台_牛客网
来源:牛客网
题目描述
在扑克牌中有种玩法叫做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=1/3
4. 每张牌只能使用一次,可以任意调换数字的顺序,可以使用任意的括号来改变运算顺序。
5. 玩家需要找到至少一种解决方案。如果无法用四张牌得到24点,则说明没有解。
现在需要你判断某种情况下是否有解。
输入描述:
第一行一个正整数 T (1≤T≤1000),表示数据的组数。 接下来 T 行,每行四个字符串,表示取出的四张牌的点数,输入的扑克牌点数只会出现 `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
输出
YES YES YES NO YES
思路
暴搜 先处理两个数再处理两个数的加减乘除与另外两个数进行计算
代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
int t;
vector<double>b;
string a[5];
int tos(string c){
if(c=="A")return 1;
if(c=="J")return 11;
if(c=="Q")return 12;
if(c=="K")return 13;
return stoll(c);
}
bool dfs(vector<double>&b){
int n=b.size();
if(n==1&&fabs(b[0] - 24.0) < 1e-6)return 1;
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(i!=j){
vector<double>nb;
for(int k=0;k<n;k++){
if(i!=k&&j!=k){
nb.push_back(b[k]);//剩下的两个数加入新数组
}
}
for(int op=1;op<=4;op++){
double res=0;
//计算原来选定的两个的数
if(op==1){
res=b[i]+b[j];
}
if(op==2){
res=b[i]-b[j];
}
if(op==3){
res=b[i]*b[j];
}
if(op==4){
if(b[j]!=0){
res=b[i]/b[j];
}
}
nb.push_back(res);
if(dfs(nb))return 1;
nb.pop_back();
}
}
}
}
return 0;
}
signed main() {
cin>>t;
while(t--){
b.clear();
for(int i=0;i<4;i++){
cin>>a[i];
b.push_back(tos(a[i]));
}
if(dfs(b))cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
return 0;
}
I 正义从不打背身
链接:登录—专业IT笔试面试备考平台_牛客网
来源:牛客网
题目描述
*"正义之枪从不打背身"*。小x最近迷上了无畏契约,钟爱"正义"这把武器。可他使用该武器有一条原则:不击杀(打不中)背对自己的敌人。小x实力强大,对于所有直面自己的敌人都能一击毙命。
在一次游戏中。小x面前有nnn个点位,从左往右序依次为1,2,3,……,n每个点位上都有一个敌人。
每个敌人 要么正面朝向小x,要么背面朝向小x。
小x实力强大,打算强迫这n个敌人玩m轮小游戏之后再对每个人开枪。
游戏规则如下:
在第iii轮小游戏中,依次执行以下所有操作:
* 序号为[1,i]的点位上的敌人位置改变。改变规则为: 从1,2,3,……,i 变为i,i−1,……,3,2,1(原来位于i号位置的敌人更换到1号位置,位于i-1号位置的敌人更换到2号位置……)
* 序号为[1,i]的点位上的敌人原地旋转180°。
所有小游戏过后,小x想知道。目前在每个点位的敌人是否被击败。
输入描述:
第一行输入两个整数 n,m 接下来一行输入一个仅由'P'和‘B'组成的字符串s。si=′P′表示第i个点位的敌人当前正面对小x。si=′B′表示第i个点位的敌人当前正背对小x。 对于所有数据保证:1≤m≤n≤2×106。∣s∣=n
输出描述:
输出一行n个整数。对于第i个数,如果目前位于第i个点位的敌人被击败则输出1,否则输出0。
示例1
输入
3 3 PPP
输出
0 0 1
思路
找规律 6 4 2 1 3 5
代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
int n,m,a[2000005];
map<int,char>mp;
deque<int> dq;
char ss[2000005], ss1[2000005];
signed main() {
cin >> n >> m;
for (int i = 1; i <= n; i++) {
cin >> ss[i];
}
for (int i = 1; i <= m; i++) {
if ((m - i + 1) % 2 == 1) {
if (ss[i] == 'P') ss[i] = 'B';
else ss[i] = 'P';
}
}
int x = m;
for (int i = 1; i <= (m + 1) / 2; i++) {
ss1[i] = ss[x];
x -= 2;
}
if (m % 2 == 0) x = 1;
else x = 2;
for (int i = (m + 1) / 2 + 1; i <= m; i++) {
ss1[i] = ss[x];
x += 2;
}
for (int i = 1; i <= m; i++) {
if (ss1[i] == 'P') cout << 1 << " ";
else cout << 0 << " ";
}
for (int i = m + 1; i <= n; i++) {
if (ss[i] == 'P') cout << 1 << " ";
else cout << 0 << " ";
}
return 0;
}
K BanG Dream! It's MyGO!!!!!
链接:登录—专业IT笔试面试备考平台_牛客网
来源:牛客网
题目描述
在“BanG Dream! It's MyGO!!!”的世界里,各个乐团的演出和排练场地像星星一样被连接在一起,形成了一张美丽的网络图。每个乐团都有自己独特的演出场地和练习室,这些地点通过各种路径互相连接,组成了一张复杂的图谱。
koala作为一名热爱音乐的乐团忠实粉丝,突然有了一个灵感。他想为最喜欢的乐团设计一个独特的徽章,这个徽章需要从网络图中找出一些特别的图案来代表乐团, 比如选三条边连接到一起, 具体来说,他对以下三种图案感兴趣:
三角形:由三条边构成的连通子图,这是一种经典的图案。
三芒星:四个点形成的图案,一个点连向其他三个点。
闪电折线:一种特别的折线,由四个点按顺序连接, 即一条链。
koala想知道有多少种情况满足,你能帮帮他吗?
输入描述:
第一行包合两个整数 n,m(1≤n≤105,1≤m≤2∗105),依次表示无向图的点数和边数; 接下来 m 行,每行两个整數u,v(1≤u,v≤n1≤u,v≤n1≤u,v≤n),表示一条边(u,v)
题目保证无重边、自环
输出描述:
输出包含一个整数,表示你的答案
示例1
输入
5 5 1 2 1 3 2 3 2 4 3 5
输出
8
说明
满足条件的导出子图的边集分别为: (1,2),(1,3),(2,3) (1,2),(2,3),(2,4) (1,3),(2,3),(3,5) (1,2),(1,3),(2,4) (1,2),(1,3),(3,5) (2,4),(2,3),(3,5) (1,3),(2,3),(2,4) (1,2),(2,3),(3,5)
备注:
给定一个无向图,你需要给出三条边的导出子图是连通的情况数量。
思路
代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
int n,m,deg[100005],u[200005],v[200005],cnt1,cnt2,cnt3;
vector<int> ve[100005];
bool vis[100005];
struct edge{
int v,nex;
}e[200005];
void sjx(){//u,v,w三角形
for(int u=1;u<=n;u++){
for(auto i:ve[u]){
vis[i]=1;
}
for(auto i:ve[u]){
for(auto j:ve[i]){
if(vis[j])cnt1++;
}
}
for(auto i:ve[u]){
vis[i]=0;
}
}
}
signed main() {
cin>>n>>m;
for(int i=1;i<=m;i++){
cin>>u[i]>>v[i];
deg[u[i]]++;
deg[v[i]]++;
}
for(int i=1;i<=m;i++){
cnt3+=1ll*(deg[u[i]]-1)*(deg[v[i]]-1);
if(deg[u[i]]>deg[v[i]] || (deg[u[i]]==deg[v[i]] && u[i]>v[i]))
swap(u[i],v[i]);
ve[u[i]].push_back(v[i]);
}
for(int i=1;i<=n;i++)
cnt2+=1ll*deg[i]*(deg[i]-1)*(deg[i]-2)/6;
sjx();
cnt3-=3*cnt1;
cout<<cnt1+cnt2+cnt3;
return 0;
}
L koala的程序
链接:登录—专业IT笔试面试备考平台_牛客网
来源:牛客网
题目描述
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)
输出描述:
根据题意输出答案
示例1
输入
10 3
输出
3 6 9 2 7 1 8 5 10
思路
使用树状数组来处理节点的插入和删除操作
代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int maxn = 3e5 + 10;
int n, m, maxx;
int bit[maxn];
int lowbit(int x)
{
return x & -x;
}
void add(int pos, int x)
{
for (int i = pos; i <= maxx; i += lowbit(i))
bit[i] += x;
}
int finds(int k)
{
int ans = 0;
int now = 0;
for (int i = 30; i >= 0; i--) {
ans += (1 << i);
if (ans > maxx || now + bit[ans] >= k) {
ans -= (1 << i);
} else {
now += bit[ans];
}
}
return ans + 1;
}
signed main()
{
cin >> n >> m;
maxx = n;
for (int i = 1; i <= n; i++)
bit[i] = lowbit(i);
int now = 1;
while (n > 1) {
now = (now - 1 + m - 1) % n + 1;
int ans = finds(now);
add(ans, -1);
cout << ans << ' ';
n--;
}
return 0;
}