牛客周赛 Round 70(A~F)
比赛链接:
是的,这次我还是没有AK,F题写了快一小时20多分钟,E题快写了20多分钟,没时间做G了
A.小苯晨跑
题面:
现在正在晨跑的小苯面前有四个数据,他想知道这些数据是否乱飞了,请你帮他确定吧。
(如果所有数据都相等,则认为数据没有乱飞,反之则乱飞了。)
输入:
本题含有多组测试数据。
-
第一行一个正整数 $ T $ $ (1 \leq T \leq 1000)$ ,表示测试数据的组数。
-
接下来对于每组测试数据,输入包含一行四个正整数 $ a_1, a_2, a_3, a_4 $ $ (1 \leq a_1, a_2, a_3, a_4 \leq 1000)$ ,表示小苯面前的四个数据。
输出:
对于每组测试数据,输出一行一个字符串。
如果当前的数据乱飞了,则输出"YES",否则输出一个 "NO"。
(都不包含双引号。)
样例:
2
2 2 2 2
1 2 3 3
NO
YES
思路:签到,直接和第一个数比较就好了
#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
#define ll long long
#define lowbit(x) (x & -x)
#define endl "\n"// 交互题记得删除
using namespace std;
mt19937 rnd(time(0));
const ll mod = 998244353;
//const ll p=rnd()%mod;
ll ksm(ll x, ll y)
{
ll ans = 1;
while (y)
{
if (y & 1)
{
ans = ans % mod * (x % mod) % mod;
}
x = x % mod * (x % mod) % mod;
y >>= 1;
}
return ans % mod % mod;
}
ll gcd(ll x, ll y)
{
if (y == 0)
return x;
else
return gcd(y, x % y);
}
void fio()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
ll a[5];
int main()
{
fio();
ll t;
cin>>t;
while(t--)
{
ll ans=0;
for(ll i=1;i<=4;i++)
{cin>>a[i];
if(a[i]==a[1])ans++;
}
if(ans==4)
cout<<"NO"<<endl;
else cout<<"YES"<<endl;
}
return 0;
}
B.小苯过马路
题面:
小苯生活在遥远的 B 星球,这天他正在等红绿灯,已知 B 星球的交规是:红灯有 \(𝑥\)秒,绿灯有 \(𝑦\) 秒,红灯和绿灯是交替亮灯的。(红灯上的时间从 \(𝑥\)减少到 \(1\)后,再过一秒灯就会变成绿色,同时灯显示的时间也会变成 \(𝑦\);绿灯也同理。)
已知目前红绿灯颜色为 \(𝑐\),灯显示的时间为 \(𝑘\),小苯过马路需要花费的时间为 \(t\)。
遵守交规的小苯想知道,从此刻开始到他走到马路对面,最少经过多少秒,请你帮他算一算吧。(小苯一旦开始过马路就不会停下脚步。)
输入:
输入包含一行,四个数字 $ x, y, k, t $ $ (1 \leq x, y, k, t \leq 1000, t \leq y)$ 和一个字符 \(c\) 。
分别表示该路口红灯和绿灯的时间 $ x, y $,和目前灯上显示的数字 $ k $,以及小苯通过马路需要花费的时间 \(t\) 以及目前灯的颜色 $ c$ ('G' 表示绿灯,'R' 表示红灯)。
(保证输入的时间是合法的,即如果 $ c = 'G' $,则 $ k \leq y $,否则 $ k \leq x $。)
输出:
输出一行一个整数,表示小苯走到马路对面最少经过的秒数。
样例:
1:
30 30 10 10 G
————————————
10
2:
30 40 5 10 G
————————————
45
思路:简单思维,绿灯能走就走,不行就等到下次绿灯开始就走,红灯得等到绿灯才能走。
#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
#define ll long long
#define lowbit(x) (x & -x)
#define endl "\n"// 交互题记得删除
using namespace std;
mt19937 rnd(time(0));
const ll mod = 998244353;
//const ll p=rnd()%mod;
ll ksm(ll x, ll y)
{
ll ans = 1;
while (y)
{
if (y & 1)
{
ans = ans % mod * (x % mod) % mod;
}
x = x % mod * (x % mod) % mod;
y >>= 1;
}
return ans % mod % mod;
}
ll gcd(ll x, ll y)
{
if (y == 0)
return x;
else
return gcd(y, x % y);
}
void fio()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
ll a[5];
int main()
{
fio();
ll x,y,k,t;
char f;
cin>>x>>y>>k>>t>>f;
ll ans=0;
if(f=='G')
{
if(t<=k)
ans=t;
else
ans=k+x+t;
}
else
{
ans+=k+t;
}
cout<<ans<<endl;
return 0;
}
C.小苯的字符串染色
题面:
小苯有一个长度为 $ n $ 的字符串 $ s $ ,其中有一些字符是黑色的,其余则为白色,他希望你可以给$ s $ 涂色,使得涂完后的 $ s $ 是纯白色的。
具体的涂色操作:
- 选择一个长度为奇数的区间 $ [l, r]$ $ (1 \leq l \leq r \leq n)$ 同时 $ r - l + 1$ 是奇数,接着将区间内的字符按照:白黑白黑白…的方式涂色,即白色开头、白色结尾、同时黑白交替的样式。
小苯限制你最多进行 $ n $ 次涂色操作,请你构造一个合法涂色方案,使得涂色完后的字符串是全白色的吧,注意你不必最小化操作次数。
(注意,已经涂好颜色的地方依然可以被后续的涂色覆盖。)
输入:
本题含有多组测试数据。
第一行一个正整数 $ T (1 \leq T \leq 100) $,表示测试数据的组数。
接下来对于每组测试数据,输出包含两行:
第一行一个正整数 $n (1 \leq n \leq 5000) $,表示字符串 $s $ 的长度。
第二行一个长度为 $ n $的 01 串 $ s $。(保证 $s $ 仅有字符 '0' 和 '1' 构成,其中 '0' 代表白色,'1' 代表黑色。)
(保证所有测试数据中, $n $ 的总和不超过 5000。)
输出:
对于每组测试数据,第一行输出一个整数 $m (0 \leq m \leq n) $,表示进行操作的次数。
接下来 $ m $ 行,每行两个正整数 $ l, r (1 \leq l \leq r \leq n), ((r - l + 1) % 2 = 1) $,表示对 $ s_l, s_{l+1}, \cdots, s_r $ 这一段区间执行涂色操作。
(有多解输出任意即可,可以证明一定有解。)
样例:
1
6
101101
————————
2
1 3
4 6
思路:思维+遍历,简单题,对每一个单位进行操作就好了
#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
#define ll long long
#define lowbit(x) (x & -x)
#define endl "\n"// 交互题记得删除
using namespace std;
mt19937 rnd(time(0));
const ll mod = 998244353;
//const ll p=rnd()%mod;
ll ksm(ll x, ll y)
{
ll ans = 1;
while (y)
{
if (y & 1)
{
ans = ans % mod * (x % mod) % mod;
}
x = x % mod * (x % mod) % mod;
y >>= 1;
}
return ans % mod % mod;
}
ll gcd(ll x, ll y)
{
if (y == 0)
return x;
else
return gcd(y, x % y);
}
void fio()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
ll a[5];
int main()
{
fio();
ll t;
cin>>t;
while(t--)
{
ll n;
cin>>n;
string f;
cin>>f;
cout<<f.size()<<endl;
for(ll i=0;i<f.size();i++)
{
cout<<i+1<<" "<<i+1<<endl;
}
}
return 0;
}
D.小苯的能量项链
小苯有一个含有 \(𝑛\)颗珠子的“能量项链”,珠子排成一排,其中第 \(𝑖\)颗珠子的能量为 \(𝑎_𝑖\)
但是这个项链并不稳定,如果项链的珠子个数不少于 \(3\) 个,则它即将发生“崩坏”,即:除了第一颗珠子和最后一颗珠子以外的其余所有珠子都将销毁,最终只留下第一颗和最后一颗珠子。
小苯现在希望项链在“崩坏”后保留尽可能多的能量,为此他可以在崩坏前执行以下的操作:
∙
∙ 去掉项链的第一颗珠子(也就意味着项链原本的第二颗珠子将会变成第一颗)。
∙
∙ 去掉项链的最后一颗珠子(也就意味着项链原本的倒数第二颗珠子将会变成最后一颗)。
两种操作各自均需要花费 \(1\)秒时间,而现在距离项链发生“崩坏”仅剩 \(k\) 秒,小苯想知道,他最多可以保留住多少能量,请你帮他算一算吧
输入:
输出:
对于每组测试数据,输出一行一个整数表示小苯能保留的最大能量。
样例:
2
5 2
2 3 4 5 2
1 1
114514
————————
8
114514
思路:特判n=1。先判断n-k<=2,如果成立则答案为数组中的最大和次大值之和。否则用前缀和后缀数组去维护最大值,然后去询问前k+1个位置就好了,然后用后缀数组求出另一个最大值,再这k+1个最大值加和中取个最大值就好了
#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
#define ll long long
#define lowbit(x) (x & -x)
#define endl "\n"// 交互题记得删除
using namespace std;
mt19937 rnd(time(0));
const ll mod = 998244353;
//const ll p=rnd()%mod;
ll ksm(ll x, ll y)
{
ll ans = 1;
while (y)
{
if (y & 1)
{
ans = ans % mod * (x % mod) % mod;
}
x = x % mod * (x % mod) % mod;
y >>= 1;
}
return ans % mod % mod;
}
ll gcd(ll x, ll y)
{
if (y == 0)
return x;
else
return gcd(y, x % y);
}
void fio()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
ll a[650000];
ll pre[650000];
ll sub[650000];
int main()
{
fio();
ll t;
cin>>t;
while(t--)
{
ll n,k;
cin>>n>>k;
for(ll i=1;i<=n;i++)cin>>a[i];
if(n==1)
{
cout<<a[1]<<endl;
continue;
}
if(n-k<=2)
{
sort(a+1,a+1+n);
cout<<a[n]+a[n-1]<<endl;
}
else
{
for(ll i=1;i<=n;i++)
{
pre[i]=max(pre[i-1],a[i]);
}
sub[n+1]=0;
for(ll i=n;i>=1;i--)
{
sub[i]=max(sub[i+1],a[i]);
}
ll ans=a[1]+a[n];
for(ll i=1;i<=k+1;i++)
{
ans=max(ans,pre[i]+sub[n-(k-i+1)]);
}
cout<<ans<<endl;
}
}
return 0;
}
E.小苯的最短路
题面:
小苯有一个 \(n\) 个点的无向完全图,编号从 1 到 \(n\),其中 \(i\) 号点和 \(j\) 号点之间的边权为 \(i \oplus j\)。
他想知道从 1 号点出发到达所有点的最短路,请你帮他算一算吧。(其中 \(\oplus\) 表示按位异或运算。但为了避免输出数据量过大,你只需要输出到达所有点的最短路的异或和即可。)
输入:
本题含有多组测试数据。
第一行一个正整数 \(T (1 \leq T \leq 10^5)\),表示测试数据的组数。
接下来 \(T\) 行,每行一个正整数 $n (1 \leq n \leq 10^9) $ 表示完全图的点数。
输出:
对于每组测试数据,输出包含一行一个正整数 \(S\),表示到所有点的最短路的异或和,即:令 $d_i $ 表示从 1 到 $i $ 号点的最短路,则 \(S = d_1 \oplus d_2 \oplus d_3 \oplus \ldots \oplus d_n\)
样例:
3
1
2
4
————————
0
3
4
思路:画了会,发现了所有的每个\(d_i\)的值,都是\(1 \oplus i\),所以直接套用规律公式,然后看1的数量奇偶性考虑异或1就行了。规律公式直接看代码吧
#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
#define ll long long
#define lowbit(x) (x & -x)
#define endl "\n"// 交互题记得删除
using namespace std;
mt19937 rnd(time(0));
const ll mod = 998244353;
//const ll p=rnd()%mod;
ll ksm(ll x, ll y)
{
ll ans = 1;
while (y)
{
if (y & 1)
{
ans = ans % mod * (x % mod) % mod;
}
x = x % mod * (x % mod) % mod;
y >>= 1;
}
return ans % mod % mod;
}
ll gcd(ll x, ll y)
{
if (y == 0)
return x;
else
return gcd(y, x % y);
}
void fio()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
ll q(ll x)
{
if(x%4==0)
return x;
else if(x%4==1)
return 1;
else if(x%4==2)
return x+1;
else
return 0;
}
int main()
{
fio();
ll t;
cin>>t;
while(t--)
{
ll n;
cin>>n;
if(n==1)
{
cout<<0<<endl;
}
else if(n==2)
cout<<3<<endl;
else
{
//cout<<q(n)<<endl;
cout<<(q(n)^(n%2==0?0:1))<<endl;
}
}
return 0;
// 1 2 3 4 5 6 7 8 9 10
// 0 3 0 4 0 0 0 8 0 0
}
F.小苯的优雅好序列
题面:、
小苯认为满足以下任一条件的序列 $ a $ 是优雅的。
- $ |a| = 1 $ 。
- 对于所有 $ i (1 \leq i \leq |a|) $ ,都存在 $ j (1 \leq j \leq |a|, j \neq i) $ ,使得\(a_j \% a_i = 0\) 或\(a_i \% a_j = 0\) 。
小苯认为一个长度为 $ n $ 的数组 $ a $ 是好数组,当且仅当$ a $ 所有的连续子数组都优雅。即对于所有 $ l, r (1 \leq l \leq r \leq n) $ ,$ a_l, a_{l+1}, \ldots, a_r $ 都是一个优雅的序列。
现在小苯有一个数组 $ a $ 和正整数 $ k $ ,他想知道有多少个不超过$ k $ 的正整数 $ x (1 \leq x \leq k) $ ,都有:$ a_1 + x, a_2 + x, \ldots, a_n + x $ 是一个好数组,请你帮他算一算吧。
输入:
每个测试文件内都包含多组测试数据。
第一行一个正整数 $ T $ $ (1 \leq T \leq 500)$ ,表示测试数据的组数。
接下来对于每组测试数据,输入包含两行。
- 第一行两个正整数 $ n, k $ $ (1 \leq n \leq 5 \times 10^4, 1 \leq k \leq 10^9) $ ,表示数组 $ a $ 的长度。
- 第二行 $ n $ 个整数 $ a_i$ $ (1 \leq a_i \leq 10^9) $ ,表示数组 $ a $ 。
(保证所有测试数据中 $ n $ 的总和不超过 $ 6 \times 10^4 $ 。)
输出:
输出 $ T $ 行,每行两个整数 $ cnt, sum $,分别表示不同的 $ x$数字个数,以及这些 $ x$ 的和。
样例:
3
5 10
7 79 1 7 1
2 1000000000
1 2
1 100
1000000000
——————————
3 8
0 0
100 5050
思路:题目描述有问题?其实这个|是整除的意思,这里改了题面,牛客没改。对于所有数都相等时进行特判。不相等时,思考如何优化?
首先对于两个相邻且相等的数,任意x都是可以的,所以寻找相邻不相等的数,并把小值和大值用\(set<pair<ll,ll>>\)进行存储,遍历完后
对于这个\(set<pair<ll,ll>>\)进行遍历小值设为l,大值设为r,可以得出 \(\frac{x+r}{x+l}\)=z(整数),显然可得出x满足 \(\frac{r-l}{x+l}\)=z(整数)即为符合答案(这个就直接对r-l进行因数分解就好了),然后首先求出一次所有的可能答案并用\(set<ll>\)存储起来,后面就用\(set<pair<ll,ll>>\)里的数对去检验已储存的答案,不对的先用vector存起来,这次遍历完后,立马遍历vector删除不符合的数,由于每个数对都不一样,存储的答案减少的会很多,所以总体时间复杂度很小,这个也算是经典容斥方法了,类似于筛子吧。
#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
//#include<bits/stdc++.h>
#include <unordered_map>
#define ll long long
#define lowbit(x) (x & -x)
#define endl "\n"// 交互题记得删除
using namespace std;
mt19937 rnd(time(0));
const ll mod = 998244353;
//const ll p=rnd()%mod;
ll ksm(ll x, ll y)
{
ll ans = 1;
while (y)
{
if (y & 1)
{
ans = ans % mod * (x % mod) % mod;
}
x = x % mod * (x % mod) % mod;
y >>= 1;
}
return ans % mod % mod;
}
ll gcd(ll x, ll y)
{
if (y == 0)
return x;
else
return gcd(y, x % y);
}
void fio()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
ll a[650000];
ll b[650000];
set<pair<ll,ll>>p;
set<ll>q;
vector<ll>op;
int main()
{
fio();
ll t;
cin>>t;
while(t--)
{
op.clear();
q.clear();
p.clear();
ll n,f;
cin>>n>>f;
ll gs=0;
for(ll i=1;i<=n;i++)
{
cin>>a[i];
if(a[i]==a[1])
gs++;
}
if(gs==n)
{
cout<<f<<" "<<(1+f)*f/2<<endl;
continue;
}
set<ll>q;
ll ko=0;
ll zk,zr;
for(ll i=1;i<n;i++)
{
ll l=a[i],r=a[i+1];
if(l>r)
swap(l,r);
if(l==r)continue;
p.insert({l,r});
}
for(auto j:p)
{
ll l=j.first,r=j.second;
//cout<<l<<" "<<r<<endl;
op.clear();
if(ko==0)
{
r-=l;
for(ll u=1;u*u<=r;u++)
{
if(r%u==0)
{
if(u-l>=1&&u-l<=f)
{
q.insert(u-l);
}
if(r/u-l>=1&&r/u-l<=f)
{
q.insert(r/u-l);
}
}
}
ko=1;
//cout<<q.size()<<endl;
}
else
{
//cout<<r<<" "<<l<<endl;
for(auto k:q)
{
//cout<<k<<endl;
if((r+k)%(l+k)==0)
{
continue;
}
else
{
op.push_back(k);
}
}
for(auto k:op)
q.erase(k);
if(q.size()==0)
break;
}
}
ll ans=0;
for(auto j:q)
{
ans+=j;
}
cout<<q.size()<<" "<<ans<<endl;
}
}