牛客 小白107 20250118
牛客 小白107 20250118
牛客小白月赛107_ACM/NOI/CSP/CCPC/ICPC算法编程高难度练习赛_牛客竞赛OJ
A:
题目大意:给定一个 \(n\) ,根据不同的范围输出不同的结果
#include<bits/stdc++.h> using namespace std; int main() { int n,a,b,c; int cnt=0; cin>>n>>a>>b>>c; while (n>a){ n-=a; cnt++; } while (n>b){ n-=b; cnt++; } while (n>c){ n-=c; cnt++; } cout<<cnt; }
简单签到
B:
题目大意:给定一个序列,每次循环进行两种操作,求使数列元素相同的最少操作数
- 选择任意多的数加 \(1\)
- 选择任意少的数减 \(1\)
#include<bits/stdc++.h> using namespace std; int n, a; int minm=1e9, maxm=-1e9; int main() { ios::sync_with_stdio(0); cin.tie(0), cout.tie(0); cin >> n; for (int i = 0; i < n; i++) { cin >> a; if (a[i] < minm) minm = a; if (a[i] > maxm) maxm = a; } long long avg = (minm + maxm + 1) >> 1; cout <<abs(maxm-avg)+abs(minm-avg)<< ' ' << avg; return 0; }
最终的操作数只有两种情况:
- 操作1做 \(n+1\) 次,操作2做 \(n\) 次
- 操作1和操作2都做 \(n\) 次
所以输出序列的最大值减去序列的最小数向上取整即可(操作1可多做一次)
C:
题目大意:
有一个 \(n\) 行 \(m\) 列的花园,每个坐标上没有植物,现在对这个花园做 \(k\) 次如下操作
- 选择第 \(i\) 行,在没有植物的地方种下 \(x\) 植物
- 选择第 \(a\) 行 \(b\) 列,如果坐标上有植物就铲掉
操作数列由以下参数生成:
def rnd(): p=(1<<32) ret=seed seed=(seed xor ((seed<<13) mod p)) mod p seed=(seed xor ((seed>>17) mod p)) mod p seed=(seed xor ((seed<<5) mod p)) mod p return ret for t=1 to k: op[t]=(rnd() mod 2) + 1 if op[t]==1: i[t]=(rnd() mod m) + 1 x[t]=(rnd() mod (n*m)) + 1 if op[t]==2: a[t]=(rnd() mod n) + 1 b[t]=(rnd() mod m) + 1
其中 ·rnd
给出 cpp
的代码如下:
unsigned seed; unsigned rnd(){ unsigned ret=seed; seed^=seed<<13; seed^=seed>>17; seed^=seed<<5; return ret; }
其中的 \(seed\) 由输入给定,\(op[t]\) 表示第 \(t\) 次操作编号
结果只需要输出以下计算的结果
#include<bits/stdc++.h> using namespace std; const int N = 5000010; unsigned int seed; unsigned int rnd() { unsigned ret = seed; seed ^= seed << 13; seed ^= seed >> 17; seed ^= seed << 5; return ret; } long long n, m, k; long long op, i, x, a, b; long long arr[20010][210]; int main() { cin >> n >> m >> k >> seed; vector<int> st[210]; for (int i=1;i<=m;i++) for (int j=1;j<=n;j++) st[i].push_back(j); for (int t = 1; t <= k; t++) { op = (rnd() % 2) + 1; if (op == 1) { i = (rnd() % m) + 1; x = (rnd() % (n * m)) + 1; if (st[i].empty()) continue; for (auto iter:st[i]) arr[iter][i]=x; st[i].clear(); } if (op == 2) { a = (rnd() % n) + 1; b = (rnd() % m) + 1; arr[a][b]=0; st[b].push_back(a); } } long long ans = 0; for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { ans ^= arr[i][j] * ((i - 1) * m + j); } } cout << ans; return 0; }
数据量大,暴力要超时
观察操作方式可以知道,所以的操作都是对于空地进行修改
所以可以构造一个状态数组,来记录每个位置地块的状态
if (st[i].empty()) continue;//如果当前列全是空地,那就不种 for (auto iter:st[i])//记录的列空地 arr[iter][i]=x;//空地种上x st[i].clear();//这一列清空
arr[a][b]=0;//铲除对应位置上的植物 st[b].push_back(a);//在状态数组里面加入这块新空地
D:
题目大意:给出一个字符串,合并一些长 \(k\) 的字符串得到 $t $,记 \(t_{[i,j]}\) 表示 \(t\) 中 \(i\) 到 \(j\) 的子串,记 \(s\) 含有的长为 \(k\) 的子串按照左端点从左到右的顺序为 \(p_1,p_2,\dots,p_{n-k+1}\)。存在一个非负整数序列 \(a\) 满足:
- \(a_1=0\)
- \(\forall i\in [1,n-k],0\le a_{i+1}-a_i\le 1\)
- \(\forall i\in [1,n-k+1],p_i=t_{[i-a_i,i+k-1-a_i]}\)
设对于 \(k\) 生成的 \(t\) 最短长度为 \(l_k\) ,求出 \(\bigoplus_{i=1}^ni\times l_i\)
#include<bits/stdc++.h> using namespace std; int l[5000010]; int main() { string str; int n; cin>>n>>str; int cnt=0; for (int i=1;i<n;i++){ if (str[i]==str[i-1]){ cnt++; l[cnt]--; }else cnt=0; } for (int i=n;i>1;i--) l[i-1]+=l[i]; long long ans=0; for (int k=1;k<=n;k++) ans^=(long long)k*(l[k]+n); cout<<ans<<endl; return 0; }
题面很臭,弯弯绕绕,本质是问一个序列,将长度大于 \(l_k\) 的部分压缩到 \(l_k\) ,问最后的序列长度 (\(t\))
以 aabbbaaa
为例,当 \(k=2\) 时有:p1=aa,p2=ab,p3=bb,p4=bb,p5=ba,p6=aa,p7=aa
因为需要满足 \(\forall i\in [1,n-k+1],p_i=t_{[i-a_i,i+k-1-a_i]}\),所以\(p_3=p_4\),对应的 \(a_4=a_5=1,a_7=2\)
此时有 \(p_3=p_4=t_{[3,4]}\)
对读入的字符串进行预处理,计算每个有连续字符的子串对整体的贡献 cnt++; l[cnt]--;
然后从第 \(n\) 项往回递推,计算每个 \(k\) 下对应的应该减去的长度,最后套公式计算即可
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具