牛客小白月赛91 题解
A. Bingbong的化学世界 签到
题意:
给你苯环的结构,判断类型。
思路:
按照区别特判即可。
代码:
#include<bits/stdc++.h>
using namespace std;
#define ff first
#define ss second
#define pb push_back
#define all(u) u.begin(), u.end()
#define endl '\n'
#define debug(x) cout<<#x<<":"<<x<<endl;
typedef pair<int, int> PII;
typedef long long LL;
const int inf = 0x3f3f3f3f;
const int N = 1e5 + 10, M = 105;
const int mod = 1e9 + 7;
const int cases = 0;
void Showball(){
vector<string> s(6);
for(int i=0;i<6;i++) cin>>s[i];
int cnt=0;
if(s[0][3]=='|') cnt++;
if(s[5][3]=='|') cnt++;
cout<<(!cnt?"o":(cnt==1?"m":"p"));
}
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int T=1;
if(cases) cin>>T;
while(T--)
Showball();
return 0;
}
B. Bingbong的数数世界 博弈
题意:
给定一个长度为
每轮必须删一个偶数,同时可以选择删除一个奇数。A先手操作,无法操作的人失败。每个人采取最优策略,求获胜者。
思路:
因为长度为
代码:
void Showball(){
int n;
cin>>n;
if(n%4==0) cout<<"Bong\n";
else cout<<"Bing\n";
}
C. Bingbong的蛋仔世界
题意:
在一个
思路:
我们只需要求出每个蛋仔到达中心的最短距离即可。这个距离就是曼哈顿距离。
代码:
void Showball(){
int n,m,k;
cin>>n>>m>>k;
int minn=max(n/2,m/2);
int sx=n/2+1,sy=m/2+1;
int cnt=0;
while(k--){
int x,y;
cin>>x>>y;
int dis=abs(x-sx)+abs(y-sy);
if(dis<=minn) cnt++;
}
cout<<cnt<<endl;
}
D. Bingbong的奇偶世界 DP
题意:
给你一个长度为
思路:
考虑
1.当前位为偶数 那么之前所有的情况都可以拼接当前位构成新的合法情况,并且当前位本身也是一个合法情况。 维护cnt和ans
2.当前位为奇数 和偶数一样,但是不更新ans,只更新cnt
3.当前位为0 由于前导0的存在,所以0不能作为开头,因此维护cnt时需要-1。
代码:
void Showball(){
int n;
cin>>n;
string s;
cin>>s;
LL ans=0,cnt=0;
for(int i=0;i<n;i++){
if(s[i]=='0'){
ans=(ans+cnt+1)%mod;
cnt=(cnt*2)%mod;
}else if(s[i]&1){
cnt=(cnt*2+1)%mod;
}else{
ans=(ans+cnt+1)%mod;
cnt=(cnt*2+1)%mod;
}
}
cout<<ans<<endl;
}
E. Bingbong的字符串世界 子序列自动机
题意:
给你一个长度为
1.字符串长度大于等于k。
2.字符串既包含ACCPET子序列,又不包含WA子序列。
求出
思路:
定义
那么我们就可以求出任意子序列第一次出现的尾字母下标。
这样我们就可以维护ACCEPT和WA的子序列位置。
并且维护字符串长度大于等于k,更新答案即可。
代码:
int n,k;
string s;
//子序列自动机
int nxt[N][27];//表示从第i个位置第一次出现j的下标
void get_next(){
for(int i=n;i>=0;i--){
for(int j=0;j<26;j++){
if(i==n) nxt[i][j]=n;
else nxt[i][j]=nxt[i+1][j];
}
if(i!=n) nxt[i][s[i]-'A']=i;
}
}
int get_pos(int st,string s){
int first=1;
for(auto ch:s){
if(first) st=nxt[st][ch-'A'];
else st=nxt[st+1][ch-'A'];
first=0;
if(st==n) return st;
}
return st;
}
void Showball(){
cin>>n>>k>>s;
get_next();
string ac="ACCEPT",wa="WA";
LL ans=0;
for(int i=0;i<n;i++){
int r1=get_pos(i,ac),r2=get_pos(i,wa);
r1=max(r1,i+k-1);
ans=ans+max(r2-r1,0);
}
cout<<ans<<endl;
}
F. Bingbong的幻想世界 拆位+算贡献
题意:
思路:
看到异或,区间;想到拆位。因为异或运算每位之间互相不影响。通过拆位后,我们只用考虑
那么如果当前位为
代码:
void Showball(){
int n;
cin>>n;
vector<int> a(n);
for(int i=0;i<n;i++) cin>>a[i];
LL ans=0;
for(int bt=0;bt<=20;bt++){
LL v0=0,v1=0;
for(int i=0;i<n;i++){
if(a[i]>>bt&1){
ans=(ans+v0*(n-i)%mod*(1<<bt)%mod)%mod;
v1+=i+1;
}else{
ans=(ans+v1*(n-i)%mod*(1<<bt)%mod)%mod;
v0+=i+1;
}
}
}
cout<<2LL*ans%mod<<endl;
}
G. Bingbong的回文路径 LCA+哈希
题意:
给你一棵根节点为1的树。每个节点包含一个小写字母,接着给你
思路:
提到最短路径,自然想到要求LCA,这里采用倍增求LCA。判断回文串,我们就可以采用维护正序,逆序的哈希值。直接比较哈希值是否相同即可。
题目唯一的难点就是合并哈希值,细节较多,这里详细展开一下。
降序哈希
升序哈希
然后拼接即可,注意还需要处理一下前半部分的幂次,逆元用快速幂即可。
代码:
vector<int> e[N];
LL depth[N],fa[N][25];
LL h1[N],h2[N],p[N];
string a;
void bfs(int root){
memset(depth,0x3f,sizeof depth);
depth[root]=1;
h1[root]=a[root]-'a'+1,h2[root]=a[root]-'a'+1;
queue<int> q;
q.push(root);
while(!q.empty()){
int u=q.front();
q.pop();
for(auto v:e[u]){
if(depth[v]>depth[u]+1){
depth[v]=depth[u]+1;
q.push(v);
fa[v][0]=u;
for(int i=1;i<=20;i++){
fa[v][i]=fa[fa[v][i-1]][i-1];
}
h1[v]=(h1[u]*P%mod+(a[v]-'a'+1))%mod;//降序哈希
h2[v]=(h2[u]+p[depth[v]-1]*(a[v]-'a'+1)%mod)%mod;//升序哈希
}
}
}
}
int lca(int a,int b){
if(depth[a]<depth[b]) swap(a,b);
for(int i=20;i>=0;i--){
if(depth[fa[a][i]]>=depth[b]){
a=fa[a][i];
}
}
if(a==b) return a;
for(int i=20;i>=0;i--){
if(fa[a][i]!=fa[b][i]){
a=fa[a][i];
b=fa[b][i];
}
}
return fa[a][0];
}
LL qmi(LL a,LL b,LL mod){
LL res=1%mod;
while(b){
if(b&1) res=res*a%mod;
a=a*a%mod;
b>>=1;
}
return res;
}
void Showball(){
int n;
cin>>n>>a;
a="?"+a;
for(int i=1;i<=n;i++){
int f;
cin>>f;
if(f){
e[f].pb(i);
e[i].pb(f);
}
}
p[0]=1;
for(int i=1;i<=n;i++) p[i]=(p[i-1]*P)%mod;
bfs(1);
depth[0]=0;
int m;
cin>>m;
while(m--){
LL u,v,p1,p2;
cin>>u>>v;
int f=lca(u,v);
//处理正序哈希
p1=(h2[u]-h2[fa[f][0]]+mod)%mod*qmi(p[depth[f]-1],mod-2,mod)%mod;
p2=(h1[v]-h1[f]*p[depth[v]-depth[f]]%mod+mod)%mod;
LL ans1=(p1*(p[depth[v]-depth[f]])%mod+p2)%mod;
//处理逆序哈希
p1=(h2[v]-h2[fa[f][0]]+mod)%mod*qmi(p[depth[f]-1],mod-2,mod)%mod;
p2=(h1[u]-h1[f]*p[depth[u]-depth[f]]%mod+mod)%mod;
LL ans2=(p1*(p[depth[u]-depth[f]])%mod+p2)%mod;
cout<<(ans1==ans2?"YES\n":"NO\n");
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效