"现代汽车前瞻杯"2025牛客暑期多校训练营3
F Flower
题意简化:
有一朵初始有n片花瓣的花,Yuki会按轮次摘花瓣:每轮操作中,她先摘a片花瓣,之后再摘b片花瓣;若剩余花瓣不足,就把剩下的全部摘完。这个过程会持续到所有花瓣被摘完为止。
Yuki的规则是:当且仅当最后一片被摘下的花瓣属于某一轮中“先摘的a片”时,她会离开;否则,她会留下。
你的任务是:先摘下一部分花瓣(但不能全摘完,至少要留1片),使得Yuki最终会留下。请计算你需要摘下的最少花瓣数;如果无论你怎么先摘(不摘完)都无法让她留下,则输出“Sayonara”。
输入数据:
- 第一行输入一个整数t(1≤t≤100),表示测试用例的数量。
- 每个测试用例包含三个整数n、a、b(1≤n,a,b≤10⁹),分别表示初始花瓣数、每轮先摘的花瓣数、每轮后摘的花瓣数。
思路
分类讨论
- n<=a 必然无法留下
- 如果n>a and n<=a+b ,为了让她留下可以不摘,
- n%(a+b)>a,说明摘完有限论之后,剩下的比a多,那么不摘也可以让她留下
- 除去上述的情况,那摘取n%(a+b)个,就可以让她最后摘完b个花瓣
点击查看代码
//"现代汽车前瞻杯"2025牛客暑期多校训练营3
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void solve() {
ll n, a, b;
cin >> n >> a >> b;
if (n <= a) {
cout << "Sayonara\n";
} else if (n > a && n <= a + b || n % (a + b) > a) {
cout << 0 << "\n";
}else {
cout << n % (a + b) << "\n";
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int _ = 1;
cin >> _;
while (_--) {
solve();
}
return 0;
}
D
Distant Control
你有n个机器人朋友,按顺序排成一排,标号从左到右为1, 2, ..., n。初始时,有些机器人是关闭的(状态为0),有些是开启的(状态为1)。
你的手机可以远程控机器人的电源状态,但有特定限制:存在一个常数a(1≤a≤n-1),你只能执行以下两种操作:
- 选择连续的a个全部处于开启状态的机器人,将它们全部关闭。
- 选择连续的a+1个全部处于关闭状态的机器人,将它们全部开启。
你的目标是:通过执行若干次操作(可以不执行任何操作),使最终处于开启状态的机器人数量尽可能多,求出这个最大可能值。
输入数据:
- 第一行输入一个整数t(1≤t≤4×10⁴),表示测试用例的数量。
- 每个测试用例包含两行:
- 第一行是两个整数n和a(2≤n≤2×10⁵,1≤a≤n-1),分别表示机器人总数和操作相关的常数。
- 第二行是一个长度为n的字符串s,由'0'和'1'组成,其中s[i]表示第i个机器人的初始状态('1'为开启,'0'为关闭)。
保证所有测试用例的n的总和不超过4×10⁵。
思路
可以思考到只要存在连续的a个开启的机器人,或者a+1个全部关闭的机器人,那么就可以通过不断操作使得全部开启
否则就是初始开的机器人数量
点击查看代码
//"现代汽车前瞻杯"2025牛客暑期多校训练营3
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void solve() {
ll n, a, cnt = 0;
cin >> n >> a;
string s;
cin >> s;
bool ok = false;
for (ll i = 0; i < n; i++) {
ll j;
if (s[i] == '1') {
for (j = i; j < i + a && j < n; j++) {
if (s[j] != '1') {
break;
}
}
if (j - i == a) {
ok = true;
}
} else {
for (j = i; j < i + a + 1 && j < n; j++) {
if (s[j] != '0') {
break;
}
}
if (j - i == a + 1) {
ok = true;
}
}
i = j - 1;
}
if (ok) {
cout << n << "\n";
} else {
for (ll i = 0; i < n; i++) {
if (s[i] == '1') {
cnt++;
}
}
cout << cnt << "\n";
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int _ = 1;
cin >> _;
while (_--) {
solve();
}
return 0;
}
J Jetton
题意简化:
Yuki和Ena进行回合制扑克游戏,初始时Yuki有x个筹码,Ena有y个筹码。每轮的胜负与支付规则如下:
- 若两人筹码数不同,筹码少的一方获胜;
- 若两人筹码数相同,Yuki获胜;
- 输的一方需向胜者支付“胜者当前拥有的筹码数”等量的筹码。
当任意一方的筹码变为0时,游戏立即结束。请判断游戏是否会在有限轮数内结束;若会,还需计算从开始到结束的总轮数。
输入数据:
- 第一行输入整数t(1≤t≤10⁵),表示测试用例数量。
- 每个测试用例输入两个整数x和y(1≤x,y≤10⁹),分别为Yuki和Ena的初始筹码数。
思路
暴力测试,目测应该不会超过100轮
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define endl "\n"
const int maxn=110;
using ll=long long ;
const ll pr=1ll<<34;
int cnt;
void solve(){
int x,y;
cin>>x>>y;
cnt=0;
while(x && y){
if(x<y){
int t=x;
x+=t;
y-=t;
}
else if(x>y){
int t=y;
y+=t;
x-=t;
}
else {
int t=x;
x+=t;
y-=t;
}
++cnt;
if(cnt>100)
{
cout<<-1<<'\n';
return;
}
}
cout<<cnt<<endl;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int T = 1;
cin >> T;
while(T--){
solve();
}return 0;
}
E Equal
题意简化:
Yuki 给你一个长度为 n 的正整数序列 a₁, a₂, ..., aₙ,你可以任意次数执行以下两种操作:
- 操作1:选择两个位置
i和j(要求1≤i<j≤n),再选一个正整数d(要求d能同时整除aᵢ和aⱼ,即d是aᵢ和aⱼ的公约数);然后将aᵢ更新为aᵢ/d,aⱼ更新为aⱼ/d。 - 操作2:选择两个位置
i和j(要求1≤i<j≤n),再选一个任意正整数d;然后将aᵢ更新为aᵢ×d,aⱼ更新为aⱼ×d。
你的目标是判断:通过执行若干次上述操作后,能否让序列中所有元素都相等(即 a₁=a₂=...=aₙ)。
输入数据:
- 第一行输入一个整数
t(1≤t≤10⁵),表示测试用例的数量。 - 每个测试用例包含两行:
- 第一行是序列长度
n(1≤n≤10⁶); - 第二行是
n个正整数a₁, a₂, ..., aₙ(1≤aᵢ≤5×10⁶),代表初始序列。
- 第一行是序列长度
- 保证所有测试用例的
n之和不超过 2×10⁶(避免输入规模过大)。
思路
对于操作题的思考,可以考虑几种操作是否有神奇的组合达到化繁为简的效果
首先使得所有数相等,那么必然所有数的素因子个数相同
而通过两次操作,可以使得一个数*d,一个数不变,一个数/d,达到因数个数的转移,于是只有因数出现过偶数次或者n-因数次数是偶数就可以达到所有数相等
注意到n=2时直接判断两个数是否相同
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define endl "\n"
using ll=long long ;
const ll pr=1ll<<34;
int cnt=0;
int n,m;
const int maxn=1e6;
bool isprime[maxn*5];
int s[maxn];
int top=0;
void ola(){
isprime[1]=1;
for(int i=2;i<=maxn*5;++i){
if(!isprime[i])
s[++top]=i;
for(int j=1;j<=top && i*s[j]<=maxn*5;++j){
isprime[i*s[j]]=1;
if(i%s[j]==0) break;
}
}
// cout<<top<<endl;
}
void solve(){
cin>>n;
unordered_map<int,int>a;
int w[3];
for(int i=1;i<=n;++i){
int x;
cin>>x;
if(i<=2) w[i]=x;
for(int j=1;j<=top && x>=s[j];++j){
while(x%s[j]==0 && x!=1){
x/=s[j];
a[s[j]]++;
}
if(isprime[x]==0){
a[x]++;
break;
}
}
}
if(n==1){
cout<<"YES"<<endl;
return ;
}
else if(n==2){
if(w[1]!=w[2]) cout<<"NO"<<endl;
else cout<<"YES"<<endl;
return ;
}
for(auto [x,y]:a){
//cout<<x<<" "<<y<<endl;
y%=n;
if((n-y)%2!=0 && y%2!=0){
cout<<"NO"<<endl;
return ;
}
}
cout<<"YES"<<endl;
return ;
}
int main(){
//ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int T = 1;
cin >> T;
ola();
while(T--){
solve();
}return 0;
}
A Ad-hoc Newbie
题意简化:
给定一个长度为 n 的正整数序列 f₁, f₂, ..., fₙ(满足每个 fᵢ 都在 1 ≤ fᵢ ≤ i 范围内),需要你构造一个 n阶方阵A(即行数和列数均为 n 的矩阵),同时满足以下3个条件:
- 元素范围:矩阵中每个元素
Aᵢⱼ(第i行第j列)都满足0 ≤ Aᵢⱼ ≤ n; - 行mex条件:对每一行
i,这一行所有元素的mex值等于fᵢ; - 列mex条件:对每一列
i,这一列所有元素的mex值也等于fᵢ。
其中,mex(最小未出现非负整数)的定义是:对于一个序列,mex 是最小的、没有在序列中出现过的非负整数(例如:序列 [0,1,3] 的 mex 是 2,序列 [1,2] 的 mex 是 0)。
题目保证:对任意合法的 f 序列,都存在满足条件的矩阵,你只需构造出任意一个即可。
输入数据:
- 第一行输入整数
t(1 ≤ t ≤ 2×10⁴),表示测试用例的数量; - 每个测试用例包含两行:
- 第一行是整数
n(1 ≤ n ≤ 1414),表示序列长度和矩阵的阶数; - 第二行是
n个整数f₁, f₂, ..., fₙ(1 ≤ fᵢ ≤ i),表示给定的序列;
- 第一行是整数
- 保证所有测试用例的
n²之和不超过2×10⁶(避免矩阵规模过大)。
思路
构造题
对角线元素a[i][i]初始为 1,确保每行 / 列包含数字 1。
对于i < j的位置,a[i][j]和a[j][i]均设为i+1,保证矩阵对称(行i和列i的元素完全相同),后续只需保证行mex正确,列mex自然也正确。
当\(f_i = 1\)时:mex=1意味着 “0 必须出现,1 必须不出现”。原对角线a[i][i]是 1,修改为 0 后:
行i中包含 0(满足 “0 出现”);
行i中不再有 1(满足 “1 不出现”),因此mex为 1。
当\(f_i > 1\)时:mex=x意味着 “0,1,...,x-1 必须全部出现,x 必须不出现”。修改a[i][x-1]和a[x-1][i]为 0 后:
行i中包含 0(通过a[i][x-1] = 0);
行i中包含 1(对角线a[i][i]仍为 1);
行i中包含 2 到 x-1(由初始化时的j+1保证,j从 1 到 x-2 时,j+1恰好覆盖 2 到 x-1);
行i中不包含 x(通过初始化逻辑和x ≤ i的约束,可证明 x 不会出现在行i中)。
因此mex为 x,满足要求。
给出一种构造代码
点击查看代码
#include<bits/stdc++.h>
using namespace std;
int t,a[1500][1500],n,x;
int main(){
cin>>t;
while(t--){
cin>>n;
for(int i=1;i<=n;i++){
a[i][i]=1;
for(int j=i+1;j<=n;j++){
a[i][j]=a[j][i]=i+1;
}
}
for(int i=1;i<=n;i++){
cin>>x;
if(x==1){
a[i][i]=0;
}
else {
a[i][x-1]=a[x-1][i]=0;
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
cout<<a[i][j]<<" ";
}
cout<<"\n";
}
}
return 0;
}
Bitwise Puzzle
题意简化
给定三个非负整数 $ a, b, c $,可进行最多 64 次以下操作(四选一执行):
- $ a $ 乘以 2;
- $ b $ 向下取整除以 2;
- $ a $ 与 $ b $ 按位异或(结果赋给 $ a $);
- $ b $ 与 $ a $ 按位异或(结果赋给 $ b $)。
要求通过这些操作使 $ a = b = c $,若存在解则完成操作,否则报告无解(题目保证:若有解,步骤不超过 64 次)。
数据范围
- 测试用例数 $ t : 1 \leq t \leq 10^4 $;
- 每个用例的 $ a, b, c : 0 \leq a, b, c < 2^{31} $;
- 操作次数上限:最多 64 次。
思路
1. 无解判定
当且仅当 $ a = b = 0 $ 且 $ c \neq 0 $ 时,无解(因操作无法从0生成非零值)。
2. 构造解的阶段化调整策略
若有解,通过分阶段调整 $ a $ 和 $ b $,最终使 $ a = b = c $,且操作次数不超过64次:
(1)对齐最高位
通过最多1次异或操作($ b \leftarrow b \oplus a $),让 $ a $ 和 $ b $ 的最高位相同,为后续调整提供“高位辅助”(确保 $ b $ 能参与 $ a $ 的高位翻转)。
(2)高位匹配 $ c $
让 $ a $ 不断乘2(左移,操作1),同时用异或操作($ a \leftarrow a \oplus b $,操作3)调整 $ a $ 的位:
由于 $ b $ 最高位为1,异或可翻转 $ a $ 的对应位,使 $ a $ 在“乘2推进高位”的过程中,逐步与 $ c $ 的高位匹配。
(3)低位匹配 $ c $
当 $ a $ 与 $ c $ 的最高位一致后,让 $ b $ 不断除以2(右移,操作2),同时继续用异或操作(操作3)调整 $ a $ 的低位,使 $ a $ 完全匹配 $ c $。
(4)同步 $ b $ 到 $ c $
将 $ b $ 除至0后,执行1次异或操作($ b \leftarrow b \oplus a $,操作4),此时 $ b = 0 \oplus a = a = c $,最终实现 $ a = b = c $。
核心思想
利用a,b的最高位,用异或分别将a的左右侧调整为与c一致,最后b=0,b^=a
点击查看代码
/*
▃▆█▇▄?
?◤? ◥█▎
◢◤ ? ?▉
?◤ ▂ ?? ▕█▎
◤ ?▅?◥▄ ?◣ █▊
? ▕▎◥?◣◤ ◢██
█◣ ◥▅█? ?██◤
?█?▂ ◢██◤
◥██◣ ◢▄◤
?██▅▇?
为什么要看我的屎代码?怎么会有这么臭的代码啊(悲)
*/
#include<bits/stdc++.h>
using namespace std;
#pragma GCC optimize(2)
#pragma GCC optimize("O3")
using ll=long long;
#define endl "\n"
using pii=pair<ll,ll>;
const int maxn=2e5+10;
const int mod=1e9+7;
const ll inf=1e18;
int dx[] = {-1, 1, 0, 0, 0};
int dy[] = {0, 0, -1, 1, 0};
mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
inline ll read() {
ll x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9') {
if(ch=='-') f=-1;
ch=getchar();
}
while(ch>='0' && ch<='9')
x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
return x*f;
}
void print(ll x) {
if(x<0)
putchar('-'),x=-x;
if(x>9)
print(x/10);
putchar(x%10+'0');
return;
}
ll qpow(ll a,ll b,ll p) {
a%=p;
ll res=1;
while(b) {
if(b&1) res=res*a%p;
b>>=1;
a=(a*a)%p;
}
return res%p;
}
ll inv(ll a,ll p) {
return qpow(a,p-2,p)%p;
}
inline ll lowbit(ll x) {
return x&(-x);
}
inline ll gcd(ll a,ll b) {
while(b) {
ll c=b;
b=a%b;
a=c;
}
return a;
}
ll lcm(ll a ,ll b) {
return a*b/gcd(a,b);
}
#define lg __lg
void solve() {
ll a=read(),b=read(),c=read();
if(a==0 && b==0 && c>0){
puts("-1");
return ;
}
if(a==b && b==c){
puts("0");
puts("");
return ;
}
vector<int> ans;
if(lg(b)<lg(a)){
b^=a;
ans.push_back(4);
}
for(int i=30;i>lg(b);--i){
if(((a>>lg(b))&1)!=((c>>i)&1)){
a^=b;
ans.push_back(3);
}
a*=2;
ans.push_back(1);
}
for(int i=lg(b);i>=0;--i){
if(((c>>i)&1)!=((a>>i)&1)){
a^=b;
ans.push_back(3);
}
b/=2;
ans.push_back(2);
}
ans.push_back(4);
print((ll)ans.size());
puts("");
for(auto x:ans) {
print(x);
putchar(' ');
}
puts("");
return ;
}
int main() {
ll _=1;
ios::sync_with_stdio(0);
cin.tie(nullptr);
_=read();
while(_--) {
solve();
}
return 0;
}
/*******************************************
............................................
............................................
............................................
............................................
.............................1ffLf1.........
............................GGGGGGGC........
....................8CCCftCCCCC1;LLG,.......
..................:CC8CCC.CCCCCCii..........
.................CC88CCCC.CCCCCCC...........
................CC88CCCCC .8.:8CCC..........
................888 CCCCC.88888G;;,.........
,................888CC88.888888888,.........
:::...............CCC888.888888888..........
:::::............Gi1tC8f888888C88,..........
:::::::,........111tttfffffLG8888...........
:::::::::,....ii111ttttttfffttG.............
::::::::::::i111tttffffffffffttt............
::::::::::11tttttfff....fffffftt ...........
..:::::::1Lf1tff,..........fffff1...........
....,:::iiftG::::::.........,LLGtL..........
::::::;:i11t:;;;;;;::,,,,,,,,, f1ii,::,,,,,,
::::::::i11t:::::::::::::::::::f111:::::::::
::::::::111:::::::::::::::::::::t111::::::::
:::::::i1if::::::,,,,,,,,,,,,,,:i111::::::,:
,,,,,::,8G,,,,,,,,,,,,,,,,,,,,,,,tL1:,,,,,,,
,,,,,,:LGL;,,,,,,,,,,,,,,,,,,,,,,,CLf,,,,,,,
,,,,,;LGGG,,,,:,,,,,,,,,,,,,,,,,,,LGCG,,,,,,
*******************************************/

浙公网安备 33010602011771号