牛客周赛 Round 56
A 面包店故事
链接:https://ac.nowcoder.com/acm/contest/88392/A
来源:牛客网
题目描述
小镇上有一家面包店,面包以 𝑥 元的价格出售,加 𝑦 元可以多加几块培根。小歪带着
𝑛 元来到了面包店,他想知道自己能不能买到加培根的面包?
输入描述:
在一行上输入三个整数 𝑥,𝑦,𝑛(1≤𝑥,𝑦,𝑛≤100) 代表面包的价格、培根的价格和小歪带的钱。
输出描述:
如果小歪能加到培根,在一行上输出 𝑌𝐸𝑆 ;否则,直接输出 𝑁𝑂 。
示例1
输入
3 1 5
输出
YES
说明
面包加培根一共 4 元,小歪带了 5 元,他可以吃到培根!
示例2
输入
10 1 10
输出
NO
说明
面包加培根一共 11 元,小歪带了 10 元,他吃不到培根 (⋟﹏⋞) 。
题解
签到
#include<bits/stdc++.h>
using namespace std;
int x,y,n;
int main(){
int i,j,k;
cin>>x>>y>>n;
if(x+y>n)printf("NO\n");
else printf("YES\n");
return 0;
}
B 放课后故事
链接:https://ac.nowcoder.com/acm/contest/88392/B
来源:牛客网
题目描述
小 𝑆 想要举办一个纸飞机大赛,他最新研制出的纸飞机需要 𝑘 张纸才能折成。
为了制作纸飞机,他向班里的 𝑛 个人要了一些纸,第 𝑖 个人提供了 𝑎𝑖 张纸给小 𝑆 研究纸飞机。
放学了,小 𝑆 终于折好了全部的纸飞机,现在有 𝑚 个人留下来和小 𝑆 一起飞纸飞机。 最多有多少个人能分到纸飞机。
输入描述:
第一行输入三个整数 𝑛,𝑚,𝑘(1≤𝑛≤105; 0≤𝑚≤105; 1≤𝑘≤109) 代表班级同学数量、留下来的同学数量和叠一只纸飞机需要的纸的数量。
第二行输入 𝑛 个整数 𝑎1,𝑎2,…,𝑎𝑛(1≤𝑎𝑖≤109) 代表每一个同学提供的纸的数量。
输出描述:
在一行上输出一个整数,代表最多有多少个人能分到纸飞机。
示例1
输入
3 2 5
1 2 4
输出
1
说明
小 𝑆 一共收集到 7 张纸,只可以叠一架纸飞机。
示例2
输入
6 3 4
1 1 4 5 1 4
输出
4
说明
小 𝑆 一共收集到 16 张纸,可以叠 4 架纸飞机,每个人都能分到纸飞机。
题解
草率了,忘记小S自己也算一个,还有long long
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,m,k,sum,a[100005];
signed main(){
int i,j;
cin>>n>>m>>k;
for(i=1;i<=n;i++){
cin>>a[i];
sum+=a[i];
}
cout<<min(sum/k,m+1)<<endl;
return 0;
}
C 异或故事
链接:https://ac.nowcoder.com/acm/contest/88392/C
来源:牛客网
题目描述
给定 𝑡 组询问,76 每次询问都会给出一个正整数 𝑎 ,你需要在区间 [1,109]中找到两个正整数 𝑏 和 𝑐 ,使得 𝑏⊕𝑐=𝑎 。
⊕ 代表按位异或。
输入描述:
每个测试文件均包含多组测试数据。第一行输入一个整数 𝑇 (1≤𝑇≤105) 代表数据组数,每组测试数据描述如下:
在一行上输入一个整数 𝑎 ( 1≤𝑎≤109 )代表76 给出的初始数字。
输出描述:
对于每一组测试数据,在一行上输出两个正整数,代表你找到的两个值。
如果存在多个解决方案,您可以输出任意一个。
示例1
输入
3
1
5
4
输出
2 3
3 6
74 78
说明
对于第一组测试数据,(10)2 xor (11)2 = (01)2 ;
对于第二组测试数据,(011)2xor (110)2=(101)2 。
题解
我不知道正解哈,位运算这块我学的不好
我想到的就是在取出比当前的数大的2的倍数T,然后输出T和T+a,但是好像不对,125分拿75分。
大佬有知道原因的和我说下吧/(ㄒoㄒ)/~~
#include<bits/stdc++.h>
using namespace std;
#define int long long
int T,a;
signed main(){
int i,j,k;
cin>>T;
while(T--){
cin>>a;
int x=1;while(x<=a)x*=2;
cout<<x<<" "<<x+a<<endl;
}
return 0;
}
然后这是正解:
#include<bits/stdc++.h>
using namespace std;
#define int long long
int T,n;
int lowbit(int x){
return x&(-x);
}
signed main(){
int i,j,k;
cin>>T;
while(T--){
cin>>n;
if(n==1)printf("2 3\n");
else if(n==1000000000)printf("%d %d\n",lowbit(n),(n^lowbit(n)));
else printf("%d 1\n",n^1);
}
return 0;
}
D 构造故事
链接:https://ac.nowcoder.com/acm/contest/88392/D
来源:牛客网
题目描述
小 𝑆 今天在数学课上学习了三角形,他回家立马拿出了自己的 𝑛 根火柴,想知道从这 𝑛 根火柴中任选 3 根,能否组成一个周长最大的三角形。
由于小 𝑆 只会暴力枚举,所以他把这个问题交给了你,你能帮他解决这个问题吗?
输入描述:
每个测试文件均包含多组测试数据。第一行输入一个整数 𝑇(1≤𝑇≤20) 代表数据组数,每组测试数据描述如下:
第一行输入一个整数 𝑛(3≤𝑛≤104) 代表小 𝑆 的火柴数量。
第二行输入 𝑛 个整数 𝑎1,𝑎2,…,𝑎𝑛(1≤𝑎𝑖≤109) 代表每根火柴的长度。
输出描述:
对于每一组测试数据,在一行上输出一个整数,代表能组成周长最大三角形的周长;如果无论如何都无法组成三角形,直接输出 −1 。
示例1
输入
3
6
2 2 10 4 10 6
5
6 1 5 3 3
5
2 2 4 10 6
输出
26
14
-1
说明
对于第一组测试数据,有两个合法的三角形 (4,10,10) 和 (6,10,10) 。
题解
排序然后选最大的三个比较能不能构成
#include<bits/stdc++.h>
using namespace std;
#define int long long
int T,n,a[10005];
signed main(){
int i,j,k;
cin>>T;
while(T--){
cin>>n;
for(i=1;i<=n;i++){
cin>>a[i];
}
sort(a+1,a+1+n);
for(i=n;i>=3;i--){
if(a[i]<a[i-1]+a[i-2])
break;
}
if(i==2)printf("-1\n");
else cout<<a[i]+a[i-1]+a[i-2]<<endl;
}
return 0;
}
E 约会故事
链接:https://ac.nowcoder.com/acm/contest/88392/E
来源:牛客网
题目描述
情人节才刚刚过去没多久啊 (¯﹃¯∗) ,但是我们的 𝑥𝑞𝑞 已经开始备战明年的情人节了。心灰意冷的他找到小 𝑆 生成了一个虚拟对象小 𝐶 ,在一次次的模拟约会中达成“一起进入电影院”的人生成就。
𝑥𝑞𝑞 决定向小 𝐶 发送邀请。在设定中,下述情况的小 𝐶 会残忍的拒绝 𝑥𝑞𝑞 的邀请:
● 𝑥𝑞𝑞 不在 00:00 后、01:59 前(含)这段小 𝐶 的睡前手机时间里发送邀请;
● 𝑥𝑞𝑞 如果在小 𝐶 不开心时发送邀请;
接受了邀请还远远没有成功!在设定中,下述情况的小 𝐶 会在进入电影院前离去:
● 𝑥𝑞𝑞 到电影院的时间比小 𝐶 晚;
● 𝑥𝑞𝑞 给小 𝐶 准备的奶茶不是她喜欢的。
如果小 𝐶 同意了邀请,且没有中途离去,我们视为 𝑥𝑞𝑞 达成成就!让我们一起来判定——这一次, 𝑥𝑞𝑞 会成功吗。
输入描述:
第一行输入两个整数 𝑛,𝑚(1≤𝑛,𝑚≤105) 代表小 𝐶 感到开心的时间段数量和小 𝐶 喜欢的奶茶数量。
此后 𝑛 行,第 𝑖 行输入两个长度为 5 ,且形如 ℎℎ:𝑚𝑚 的字符串代表小 𝐶 第 𝑖 段感到开心的起止时间,保证每一段开心时间不超过 24 小时。除了这 𝑛 个时间段外,剩余时间她都是不开心的。
第 𝑛+1 行输入 𝑚 个长度不超过 10 且由大小写字母混合构成的字符串 𝑠1,𝑠2,…,𝑠𝑚 代表小 𝐶 喜欢喝的奶茶名字。
第 𝑛+2 行输入一个整数 𝑞(1≤𝑞≤105) 代表 𝑥𝑞𝑞 尝试次数,每次尝试描述如下:
● 第一行输入一个长度为 5,且形如 ℎℎ:𝑚𝑚 的字符串代表 𝑥𝑞𝑞 发送邀请的时间点;
● 第二行输入两个长度为 5 ,且形如 ℎℎ:𝑚𝑚 的字符串代表 𝑥𝑞𝑞 到达电影院的时间和小 𝐶 到达电影院的时间,我们约定,他们会在同一天内到达;
● 第三行输入一个长度不超过 10 且由大小写字母混合构成的字符串 𝑡 代表 𝑥𝑞𝑞 购买的奶茶名字。
本题中出现的时间格式均按照 𝐼𝑆𝑂8601 的二十四小时格式标准,即形如 ℎℎ:𝑚𝑚,其中
ℎℎ(00≤ℎℎ<24) 代表小时数,𝑚𝑚(00≤𝑚𝑚<60) 代表分钟数。
输出描述:
对于每一次尝试,如果 𝑥𝑞𝑞 成功达成成就,在一行上输出 Winner xqq ;如果 𝑥𝑞𝑞 成功邀请但是小 𝐶 中途离开,在一行上输出 Joker xqq ;否则,直接输出 Loser xqq 。
示例1
输入
3 2
00:03 00:47
00:30 01:23
12:00 17:00
Lemonade Cappuccino
5
00:35
12:00 12:00
Cappuccino
01:23
13:00 12:59
Cappuccino
01:15
11:00 12:43
WaTer
01:24
09:24 11:00
Lemonade
23:59
08:00 07:43
LeMonade
输出
Winner xqq
Joker xqq
Joker xqq
Loser xqq
Loser xqq
说明
对于第一次尝试:
● 𝑥𝑞𝑞 在 00:35 发送邀请,此时在规定时间内,且小 𝐶 是开心的,所以他的邀请会被接受;● 𝑥𝑞𝑞 在 12:00 到达电影院,此时不晚于小 𝐶 ,且携带了小 𝐶 爱喝的 𝐶𝑎𝑝𝑝𝑢𝑐𝑐𝑖𝑛𝑜 ,所以她不会中途离开。
对于第二次尝试,由于迟到了,小 𝐶 中途离开;
对于第三次尝试,由于带错了奶茶,小 𝐶 中途离开;
对于第四次尝试,由于发送邀请时小 𝐶 不开心,所以邀请失败;
对于第五次尝试,由于发送邀请时不在规定时间内,所以邀请失败。
示例2
输入
3 1
00:00 00:00
22:47 23:59
23:58 00:17
AbCdEfGhIj
1
00:00
00:00 00:00
AbCdEfGhIj
输出
Winner xqq
说明
注意,当开心的起始时间和结束时间相等时,我们认为小 𝐶 一整天都感到开心。
题解
模拟,但是!!!
我有一堆话想说!!!!
首先,你大半夜的发短信骚扰别人睡觉!
其次,这个小C这个心情冷热无常!你不行你换一个???
然后,等不了1分钟的女朋友你要了干啥!!!
最后,你在现实中你家女朋友这么多次实验??!!!
纯属的无聊题!!!
上代码
#include<bits/stdc++.h>
using namespace std;
int n,m,q,hh,mm,t[100005],tag;
string s;
int tim(int hh,int mm){
return hh*60+mm;
}
unordered_map<string,bool>mp;
int main(){
int i,j,k;
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++){
scanf("%d:%d",&hh,&mm);
int tmp=tim(hh,mm);t[tmp]++;
scanf("%d:%d",&hh,&mm);
if(tmp>tim(hh,mm))tag++;
t[tim(hh,mm)+1]--;
}
for(i=1;i<100000;i++)t[i]+=t[i-1];
for(i=0;i<100000;i++)t[i]+=tag;
for(i=1;i<=m;i++)
{
cin>>s;
mp[s]=true;
}
scanf("%d",&q);
while(q--){
int flag=2;
scanf("%d:%d",&hh,&mm);
if(hh>1||!t[tim(hh,mm)])flag=0;
scanf("%d:%d",&hh,&mm);
int tmp=tim(hh,mm);
scanf("%d:%d",&hh,&mm);
if(tmp>tim(hh,mm)&&flag)flag=1;
cin>>s;if(!mp.count(s)&&flag)flag=1;
if(flag==2)printf("Winner xqq\n");
else if(flag==1)printf("Joker xqq\n");
else printf("Loser xqq\n");
}
return 0;
}
F 不是烤串故事
链接:https://ac.nowcoder.com/acm/contest/88392/F
来源:牛客网
题目描述
小红有两个长度为 𝑛 的字符串 𝑠 和 𝑡 ,我们定义下标从 1 开始,现在你可以选取字符串
𝑠 的前 𝑖 个字符 𝑠1𝑠2⋯𝑠𝑖 ,然后将这一部分反转后与剩余部分拼接,得到 𝑠𝑖′ 。
请你找到每一个翻转前缀 𝑠𝑖′ 与字符串 𝑡 的
max
i
=
1
n
_
len
{
lcp
(
s
i
′
,
t
)
}
\max _{i=1}^{n} \_\operatorname{len}\left\{\operatorname{lcp}\left(s_{i}^{\prime}, t\right)\right\}
i=1maxn_len{lcp(si′,t)},即长度最长的 lcp(𝑠𝑖′,𝑡) 。在这里,lcp 代表最长公共前缀。
好吧,这其实并不难,作为神秘的 𝐹 题,你同时需要输出满足上述条件的最小的 𝑖 。
在本题中,反转即为将字符串绕中心字符前后反转,具体地说,设字符串为 𝑠1𝑠2⋯𝑠𝑛−1𝑠𝑛 ,反转后得到 𝑠𝑛𝑠𝑛−1⋯𝑠2𝑠1 。
输入描述:
每个测试文件均包含多组测试数据。第一行输入一个整数 𝑇 (1≤𝑇≤100) 代表数据组数,每组测试数据描述如下:
第一行输入一个整数 𝑛(1≤𝑛≤106) 代表字符串长度。
第二行输入一个长度为 𝑛 ,且仅由小写字母构成的字符串 𝑠。
第三行输入一个长度为 𝑛 ,且仅由小写字母构成的字符串 𝑡。
除此之外,保证所有的 𝑛 之和不超过 106 。
输出描述:
对于每一组测试数据,在一行上输出两个整数,代表最长 lcp 长度和在此条件下最小的
𝑖 。
示例1
输入
3
6
baabaa
aabbbb
3
abc
bac
2
ab
cd
输出
4 3
3 2
0 1
说明
对于第一组测试数据,我们这样描述整个过程:
∙ 选择前缀长度为 1 翻转 𝑠1′=“𝑏𝑎𝑎𝑏𝑎𝑎” ,lcp = 0 ;
∙ 选择前缀长度为 2 翻转 𝑠2′=“𝑎𝑏𝑎𝑏𝑎𝑎” ,lcp = 1 ;
∙ 选择前缀长度为 3 翻转 𝑠3′=“𝑎𝑎𝑏𝑏𝑎𝑎” ,lcp = 4 ;
∙ 选择前缀长度为 4 翻转 𝑠4′=“𝑏𝑎𝑎𝑏𝑎𝑎” ,lcp = 0 ;
∙ 选择前缀长度为 5 翻转 𝑠5′=“𝑎𝑏𝑎𝑎𝑏𝑎” ,lcp = 1 ;
∙ 选择前缀长度为 6 翻转 𝑠6′=“𝑎𝑎𝑏𝑎𝑎𝑏” ,lcp = 3 ;
所以最长的公共前缀为 4 ,与此同时最小的翻转下标为 3 。
题解
#include<bits/stdc++.h>
using i64 = long long;
using u64 = unsigned long long;
const int P=13331;
const i64 hash_mod = 1610612741;
void solve() {
int n;
std::cin >> n;
std::string s, t;
std::cin >> s >> t;
s = ' ' + s, t = ' ' + t;
std::vector<i64> h1(n + 1), h2(n + 1), h3(n + 1), p(n + 1);
p[0] = 1, h1[0] = 0, h3[0] = 0;
for (int i = 1; i <= n; i++) {
p[i] = p[i - 1] * P % hash_mod;
h1[i] = (h1[i - 1] * P + s[i]) % hash_mod;
h3[i] = (h3[i - 1] * P + t[i]) % hash_mod;
}
h2[0] = 0;
std::reverse(s.begin() + 1, s.end());
for (int i = 1; i <= n; i++) {
h2[i] = (h2[i - 1] * P + s[i]) % hash_mod;
}
auto get = [&] (int l, int r, std::vector<i64>& h) -> i64 {
return ((h[r] - h[l - 1] * p[r - l + 1]) % hash_mod + hash_mod) % hash_mod;
};
int mx = 0, pos = 1;
for (int i = 1; i <= n; i++) {
int l = 1, r = n;
int ans = -1;
while(l <= r) {
int mid = l + r >> 1;
i64 tar = get(1, mid, h3);
i64 num = 0;
if (mid > i) {
num = get(i + 1, mid, h1);
num = (num + get(n - i + 1, n, h2) * p[mid - i]) % hash_mod;
}
else {
num = get(n - i + 1, n - i + mid, h2);
}
if (tar == num) {
l = mid + 1;
ans = mid;
if (mid > mx) {
mx = mid;
pos = i;
}
}
else {
r = mid - 1;
}
}
}
std::cout << mx << ' ' << pos << '\n';
}
signed main() {
std::ios::sync_with_stdio(0);
std::cout.tie(0);
std::cin.tie(0);
i64 t = 1;
std::cin >> t;
while (t--) {
solve();
}
}