当前位置: 首页 > news >正文

牛客周赛94

随手写一下题解吧,最后一题确实有点烧脑了,一开始没想到,看完题解确实茅塞顿开了

经典校招题

思路:n级台阶,每次只能走1或2格,问你最少得步数,那肯定就是每次都走两个,如果是奇数就多走一个,否则就是整除

#include<bits/stdc++.h>
using namespace std;
int n;
signed main()
{cin>>n;cout<<n/2+(n%2==1);
}

小苯购物

思路:纯暴力把每种情况枚举一遍即可

#include<bits/stdc++.h>
using namespace std;
#define int long longvoid solve() {int n;cin >> n;int a[4], b[4];for(int i = 1; i <= 3; i++) {cin >> a[i] >> b[i];}int ans = n; int order[3] = {1, 2, 3};do {int current = n;for(int i = 0; i < 3; i++) {int coupon = order[i];if(current >= a[coupon]) {current = max(current - b[coupon], 0LL);}}ans = min(ans, current);} while(next_permutation(order, order + 3));cout << ans << "\n";
}signed main() {ios::sync_with_stdio(false);cin.tie(0);int t;cin >> t;while(t--) {solve();}return 0;
}

 小苯的与三角形

思路:这题其实很容易去联想位运算这个东西,众所周知,两个数的&一定会小于等于两个数之中最小的那一个,因此我们可以知道,如果y+x&y>x即可成立,那么也就是说我们的y&(y-1)都无法大于x的话,一定就是-1,否则的话,只要我们的x&y最小只需要是y的最大的那一位的1的位置,即可

#include<bits/stdc++.h>
using namespace std;
#define int long long
signed main() 
{int t;cin >> t;  while (t--) {int x;cin >> x;  if ((x & (x - 1)) == 0) {cout << -1 << endl;} else {cout << (1 << (31 - __builtin_clz(x))) << endl; }}return 0;
}

 小苯的序列染色

思路:这题其实和c题差不多都是有点考验思维,我们仔细分析一下发现,每次只能涂成110,并且初始的时候,所有数的数值都是0,因此我们可以知道,我们可以先把整个序列最左边连续的0丢掉,比如说001100,我们就可以看成1100,然后我们知道,最后一位肯定不可能是1,然后嘞,剩下的序列,第二个数绝对不可能是0,我们直接去实现上述思路即可

#include<bits/stdc++.h>
using namespace std;
#define int long long
int t;
int n;
string s;void solve() {cin >> n;cin >> s;if (s[n - 1] != '0') {cout << "NO" << endl;return;}int j = 0;while (j < n && s[j] == '0') {j++;}if (j + 1 < n && s[j + 1] == '0') {cout << "NO" << endl;return;}cout << "YES" << endl;
}signed main() {int T = 1;cin >> T;while (T--) {solve();}return 0;
}

 小苯的数字操作

思路:这题怎么说呢?我们只有两种操作,乘二和除二,那么我们考虑那种情况更特殊呢?好吧,其实都很特殊,只有奇数乘二会出现过程中不会出现的东西,只有奇数除二才会导致丢失一个1

众所周知,我们只有k次操作机会,算上一开始的数,如果全是乘法操作的话,也就是说会有k+1种情况了现在,那么我们只需要去遍历k种操作或者说等n变成1被除成0的时候结束操作即可,我们只需要在n变成奇数的时候去加上剩余的次数了并且这个奇数不为1,是1直接加1即可,偶数就直接+1

#include<bits/stdc++.h>
using namespace std;
#define int long long
int t;
int n,k;
void solve()
{cin>>n>>k;int ans=k+1;while(n&&k){if(n%2==1){if(n==1)ans+=1;elseans+=k;}else{ans+=1;}n/=2;k--;}cout<<ans<<"\n";
}
signed main()
{cin>>t;while(t--){solve();}return 0;
}

 小苯的小球分组

题意:我们先来说一下题意吧,防止到时候绕迷糊了,就是说有n个小球,每个小球都有自己的颜色,然后给你一个定义f(X)表示对于X这个序列, 满足两个条件的最小分组,第一个是每个组内最多有俩球,第二个是每个组内的球的颜色不能相同,求出所有子序列的最小分组个数之和

思路:我们首先首先来考虑两种情况

第一种是,第一组有5个球,第二组有3个球,第三组有3个球,问你最少分多少组,那么我们从谈心的角度来考虑,尽可能多的将两个异色球放在一起,所以第一组和第一组先配对三个,然后剩下的就是第一组的两个和第三组的两个配对,最后剩下一个第三种颜色的球,我们发现这种就相当于球的总个数除二去向上取整

第二种是第一组有五个球,第二组和第三组各有两个球,俺们我们的配对方式就是第一组和第二组配对两个,第一组和第三组配对两个,我们就会发现,这样的分组数,其实就是最多的球的颜色出现的个数

但是我们现在想要求出来总个数,该怎么办呢?

我们能否假设,所有子序列都是满足第一种情况的,球的总个数/2向上取整,答案是肯定的,那么我们可以用组合数的公式去求我们假设情况下总共的个数应该为

(len+1)/2*C(n,len);我们的len表示的是当前序列的长度,len直接去遍历1到n即可

这样我们就找到了所有情况下的个数总和

那我们知道有些是假设的肯定不可能是真的啊,那部分该怎么去求呢?

我们在这里去引入一个绝对众数的概念
什么是绝对众数呢?就是说当前的我们当前的众数的出现次数,要超过其余元素的出现的次数的累加和

好了解释完这个概念我们继续往下讨论,我们会发现,其实对于绝对众数的这个概念,也就是我在上面列举的第二种情况,所以我们可以去考虑枚举绝对众数,我们用一个三层循环,最外层循环式遍历的颜色,第二层循环是遍历当前颜色出现的次数,我们将第二层变成我们子序列的绝对众数即可,第三层循环,我们去遍历其余元素出现的次数,其余元素的出现次数应当小于绝对众数并且小于等于剩下的元素个数

然后我们来考虑要减掉什么,加上什么

首先就是减掉的是我们假设的那部分为子序列长度/2向上取整的那部分可能出现的子序列次数为

(j+k+1)/2*C(cnt[i],j]*C*(n-cnt[i],k)即可

那么我们加上的是什么
(j+1)/2*C(cnt[i],j]*C*(n-cnt[i],k)即可

然后就是写代码了,思路确实有点小复杂,但是学完会有好处的

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define LL long long
int t;
int n;
int x;
int mod=998244353;
int f[5005];
int inv[5005];
int fast(int a,int b)
{int base=1;while(b){if(b%2==1){base=(base*a)%mod;}a=(a*a)%mod;b/=2;}return base;
}
int C(int n,int m)
{return (f[n]*inv[m])%mod*inv[n-m]%mod;
}
void solve(){cin>>n;unordered_map<int,int> mp;for(int i=1;i<=n;i++){cin>>x;mp[x]++;}int num=mp.size();vector<int> cnt;for(auto t:mp){cnt.push_back(t.second);}int ans=0;for(int i=1;i<=n;i++){ans=(ans+(i+1)/2*C(n,i)%mod)%mod;}for(int i=0;i<num;i++){for(int j=1;j<=cnt[i];j++){for (int k = 0; k < j && k <= (n - cnt[i]); k++){int len=k+j;int del=(len+1)/2*C(n-cnt[i],k)%mod*C(cnt[i],j)%mod;int add=j*C(n-cnt[i],k)%mod*C(cnt[i],j)%mod;ans=(ans-del+add+mod)%mod;}}}cout<<ans<<"\n";
}
signed main()
{int flag=1;f[0]=1;inv[0] = 1;  for(int i=1;i<=5000;i++){flag=(flag*i)%mod;f[i]=flag;}inv[5000]=fast(f[5000],mod-2);for(int i=4999;i>=0;i--){inv[i]=inv[i+1]*(i+1)%mod;}cin>>t;while(t--)solve();return 0;
}

相关文章:

  • 极智项目 | 多模态大模型推理平台-Streamlit版(支持Qwen2.5/InternVL3/KimiVL三大模型)
  • 【CBAP50技术手册】#31 Observation(观察法):BA(业务分析师)的“现场侦探术”
  • 浮点数舍入规则_编程语言对比
  • CTFHub-RCE 命令注入-过滤运算符
  • [SC]SystemC在CPU/GPU验证中的应用(二)
  • R语言错误处理方法大全
  • CRISPR-Cas系统的小型化研究进展-文献精读137
  • python打卡day41
  • vue2源码解析——响应式原理
  • CentOS 7 安装docker缺少slirp4netnsy依赖解决方案
  • C51单片机
  • Python Day38 学习
  • Java BigInteger类详解与应用
  • 使用Yolov8 训练交通标志数据集:TT100K数据集划分
  • 【MLLM】多模态LLM 2025上半年技术发展(Better、Faster、Stronger)
  • 【C语言】讲解 程序分配的区域(新手)
  • 第12讲、Odoo 18 权限控制机制详解
  • 【plink 和vcftools使用】从 VCF 文件中提取指定 SNP 的 REF/ALT 方法
  • ICML 2025 Spotlight | 机器人界的「Sora」!让机器人实时进行未来预测和动作执行!
  • 【LLM相关知识点】 LLM关键技术简单拆解,以及常用应用框架整理(二)
  • 网站排名seo软件/关键词优化seo费用
  • 阿里巴巴网站建设分析/新站网站推广公司
  • 淘宝优惠券查询网站怎么做/百度seo权重
  • 申请个人网站建设/关键词排名优化工具有用吗
  • 商务网站的主要存在形式/商丘seo教程
  • 做国外的网站有什么不用钱的/站长工具站长