题解 |第20届纪念款-牛客周赛 Round 20

第20届纪念款-牛客周赛 Round 20 全部题解

A.赝品

考察暴力

我们只需要直接排序不等于最大的数就是赝品即可

void solve()
{
    cin>>n;
    vector<int>a(n);
    for(auto&v:a) cin>>v;
    sort(a.begin(),a.end());
    int cnt=0;
    for(auto&v:a) if(v!=a[n-1]) cnt++;
    cout<<cnt<<endl;
    return ;
}

B.小红的01连续段

考察简单性质

要是最后答案最长的是0,那么我们全部的问号变成0一定是最优的,1同理,也可以用一个虚假的dp看每一位是啥的时候的 最长连续长度

int dp[N][2];

void solve()
{
    string s; cin>>s;
    n=s.size(); s=' '+s;
    int ans=0;
    for(int i=1;i<=n;i++){
        if(s[i]=='?'){
            dp[i][1]=dp[i-1][1]+1;
            dp[i][0]=dp[i-1][0]+1;
        }
        else{
            dp[i][s[i]-'0']=dp[i-1][s[i]-'0']+1;
        }
        ans=max({ans,dp[i][0],dp[i][1]});
    }
    cout<<ans<<endl;
    return ;
}

C.小红的01串构造

考察简单性质

我们可以发现需要t对11至少需要t+1个1全部排列到一起

1.k<t+1 -1

2.接着我们优先排好t+1个1如果还有1就必须隔一个0来放,如果最后长度不够就补0,反之无解

void solve()
{
    cin>>n>>k>>t;
    string s;
    t++;
    k-=t;
    if(k<0){
        cout<<-1<<endl;
        return ;
    }
    while(t--) s+='1';
    while(k--){
        s+='0'; s+='1';
    }
    if(s.size()>n){
        cout<<-1<<endl;
        return ;
    }
    while(s.size()<n) s+='0';
    cout<<s<<endl;
    
    return ;
}

D.小红的数位删除

考察二进制暴力枚举

我们可以发现数位只有9位我们可以直接暴力枚举每个数的删除位置,这里考虑使用二进制暴力枚举比较好

void solve()
{
    int a,b; cin>>a>>b;
    string x=to_string(a),y=to_string(b);
    int cnt1=x.size(),cnt2=y.size();
    int ans=INF;
    for(int i=1;i<1<<cnt1;i++){
        int v=0;
        for(int j=0;j<cnt1;j++){
            if(i>>j&1) v=v*10+(x[j]-'0');
        }
        
        for(int j=1;j<1<<cnt2;j++){
            int w=0;
            for(int k=0;k<cnt2;k++){
                 if(j>>k&1) w=w*10+(y[k]-'0');
             }
             // 防止mod0
             if(v==0 || w==0) ans=min(ans,cnt1-(int)__builtin_popcountll(i)+cnt2-__builtin_popcountll(j));
             else if(v%w==0 || w%v==0){
                 ans=min(ans,cnt1-(int)__builtin_popcountll(i)+cnt2-__builtin_popcountll(j));
             }
        }
    }
    cout<<(ans==INF ? -1 : ans)<<endl;
    return ;

E.小红的漂亮串

考察记忆化搜索

我们明显的发现是一段很长的串当中是否有red和没有der我们可以使用数位dp记录上2个位置是什么上1个位置是什么,最后是否满足有“red”

我们可以这样思考如果当前数位确定同时前面两个字母也确定我们可以依照数位来排可以转移所以不会漏状态

int dp[N][4][4][2];
int dfs(int pos,int u1,int u2,bool ok){
    int &v=dp[pos][u1][u2];// 考虑当前位置是不是会影响后面的位置
    
    if(!pos) return ok;
    if(~v)   return v;
    int  res=0;
    for(int i=0;i<3;i++){
        if(u1==0 && u2==1 && i==2) continue;// 我们按照 d  e  r 映射一手 这个是不合理
        res+=dfs(pos-1,u2,i,ok | (u1==2&&u2==1&&i==0));
        res%=mod;
    }
    res+=23*dfs(pos-1,u2,3,ok);// 其他23个位置是一样的默认为3即可
    res%=mod;
    return v=res;
}

void solve(){
    memset(dp,-1,sizeof dp);
    cin>>n;
    cout<<dfs(n,3,3,0)<<endl;
    return ;
}

F.小红的零

考察思维+树状数组

解析参考代码内部

代码参考咸鱼小孩

// 数学公式要变形
// 莫急莫急先读题
#include <bits/stdc++.h>
using namespace std;
#define lowbit(x) (x&(-x))
#define endl "\n"
#define ios ios::sync_with_stdio(0); cin.tie(0),cout.tie(0);
#define LF(x)   fixed<<setprecision(x)// c++ 保留小数
typedef long long LL;
typedef pair<int, int> PII;
const int N=1000010,M=1010,INF=0x3f3f3f3f,mod=1e9+7;
const double pai=acos(-1.0);// pai
map<int,int> mp;
int t,n,m;
int w[N];
int cnt5[N],cnt2[N];
LL  sum5[N],sum2[N];

LL ct5[N],ct2[N];
LL sm5[N],sm2[N];

void add(LL tr[],int x,LL k){
    for(int i=x;i<=m;i+=lowbit(i)) tr[i]+=k;
}

LL query(LL tr[],int x){
    LL res=0;
    for(int i=x;i;i-=lowbit(i)) res+=tr[i];
    return res;
}

void solve()
{
    cin>>n;
    for(int i=1;i<=n;i++){
        int x; cin>>x;
        while(x%2==0) cnt2[i]++,x/=2;
        while(x%5==0) cnt5[i]++,x/=5;
        sum2[i]=sum2[i-1]+cnt2[i];
        sum5[i]=sum5[i-1]+cnt5[i];
    }
    
    // 求出前缀2 和  5 的数量
    vector<int> res;
    for(int i=1;i<=n;i++) res.push_back(sum2[i]-sum5[i]);
    
    // 我们假设固定了右端点,对于r 我们考虑左边的区间为[1,r-1],那么我们有两种情况要处理
    // 1. 对于sum5[r]-sum5[l]>=sum2[r]-sum2[l]
    // 我们考虑带来的贡献就是 满足条件的1都数量 y-> y*sum2[r]-这y个sum2[l]的和
    // 进一步推导式子可以变为 sum5[r]-sum2[r]>=sum5[l]-sum2[l]// 满足这个要求的
    // 这个时候我们就是可以来考虑前缀中满足小于这个的数量的 
    // 我们考虑树状数组来维护,同时把每一个位置的数量加入其中考虑到   有负数重复 我们离散处理即可
    
    // 2.对于sum2[r]-sum2[l]>=sum5[r]-sum5[l] 同理变形-> sum2[r]-sum5[r]>=sum2[l]-sum5[l]
    // 接着我们如果按照上面的排序的话就是和2是反过来的情况所以2就是倒着来求即可
    
    sort(res.begin(),res.end());
    
    res.erase(unique(res.begin(),res.end()),res.end());
    
    m=res.size();
    
    int pos=lower_bound(res.begin(),res.end(),0)-res.begin()+1;
    
    // 为什么要加因为考虑前缀和到0的位置
    add(ct2,pos,1ll);
    add(ct5,pos,1ll);
    
    LL ans=0;
    for(int i=1;i<=n;i++){
        int pos=lower_bound(res.begin(),res.end(),sum2[i]-sum5[i])-res.begin()+1;
        ans+=(LL)query(ct5,pos)*sum5[i]-query(sm5,pos);
        ans+=(LL)(query(ct2,m)-query(ct2,pos))*sum2[i]-(query(sm2,m)-query(sm2,pos));
        add(ct2,pos,1ll);
        add(ct5,pos,1ll);
        add(sm2,pos,sum2[i]);
        add(sm5,pos,sum5[i]);
    }
    cout<<ans<<endl;
    return ;
}
signed main ()
{
    ios// 不能有printf puts scanf
    int t=1;
    while(t--){
    	 solve();
    }
}

全部评论
把离散化的值改成sum5 - sum2就过不了了,这是玄学么
1 回复 分享
发布于 2023-11-21 20:37 河南
大佬你好,我想问一下为什么E题我用python3的记忆化搜索总是爆栈,告诉我递归超过最大深度。是语言的问题吗
点赞 回复 分享
发布于 2023-11-20 14:06 上海
怎么变为湖南科技大学了
点赞 回复 分享
发布于 2023-11-19 23:47 山西

相关推荐

渐好:软光栅真的写明白了吗,既然是软渲那技术栈不应该使用OpenGL,光追和bvh既不算什么高级渲染技术更不应该属于软渲的内容,git那个项目没啥用,建议把前两个项目重新组织一下语言,比如软渲染那个项目 冯着色和msaa、贴图这几项分开写,写的到位点,如果你还学过光追那就单独写出来,如果没把握考官问你答不上来就别写给自己找麻烦,在技术栈那一栏简单提一下自己学过就行,这样杂的放在一起不太严谨,个人愚见.
点赞 评论 收藏
分享
群星之怒:1.照片可以换更好一点的,可以适量P图,带一些发型,遮住额头,最好穿的正式一点,可以适当P图。2.内容太少。建议添加的:求职意向(随着投递岗位动态更改);项目经历(内容太少了建议添加一些说明,技术栈:用到了什么技术,还有你是怎么实现的,比如如何确保数据传输稳定的,角色注册用到了什么技术等等。)项目经历是大头,没有实习是硬伤,如果项目经理不突出的话基本很难过简历筛。3.有些内容不必要,比如自我评价,校内实践。如果实践和工作无关千万别写,不如多丰富丰富项目。4.排版建议:建议排版是先基础信息,然后教育背景(要突出和工作相关的课程),然后专业技能(一定要简短,不要长篇大论,写你会什么,会的程度就可以),然后是项目经历(一定要详细,占整个简历一定要超过一半,甚至超过百分之70都可以)。最后如果有一部分空白的话可以填补上校内获得的专业相关的奖项,没有就写点校园经历和自我评价。5.技术一定要够硬,禁得住拷打。还有作息尽量保证正常,不要太焦虑。我24双非本科还是非科班,秋招春招各找了一段实习结果都没有转正,当时都想噶了,最后6月份在校的尾巴也找到一份工作干到现在,找工作有时很看运气的不要急着自我否定。 加油
点赞 评论 收藏
分享
我是985研究生,最近学校在组织开题,大家都在非常紧张地准备,但我一直进入不了状态,很想做但是心又很浮躁。但我的室友们感觉都非常认真,每天醒来就开始看论文,睡着前最后一件事还是在看论文,我非常焦虑。我感觉自己甚至有点把大家当做假想敌了。这种比较心态还存在于生活的各种方面:看到有钱的同学会非常羡慕,看到朋友圈里面环游世界的留学生同学也会羡慕,看到那些工作后有自己的钱而过上较为阔绰的生活的时候还是羡慕,就仿佛只有自己一个人在阴暗爬行。而且这些比较是每时每刻的,为了不比较,我已经关闭了朋友圈,但是每次偶尔刷一下还是会难受很久。我知道比较是偷走幸福的小偷,但我好像控制不了,感觉自己是一个偷窥别人生活的...
若怜君欢:担心开题搞砸了,幻想拥有别人的生活,本质上是因为自卑,楼主小时候大概率是留守儿童或者父母关系很紧张,导致楼主没有安全感、焦虑、内耗。 这样的情况最好的办法就是建立自信和降低期待,建立自信不是一蹴而就,而是循序渐进,比如告诉自己允许自己第一次没把事情做好,失败了能搞清楚其中缘由而不是全盘否定自己,失败不是终点,放弃才是;降低期待只要记住一句话即可,能伴随你一生的,只有经验和学识,所以你对事情的态度应该更多地去思考它是否能带来学识和经验的增长,而不是仅仅用短期的利益作为唯一期待。 人生不是一成不变的,它是可以迭代更新的,去归纳总结自身的不足并结合实际去改进,去尝试一些新的思路和方法,不要固执钻牛角尖,也不要反复横跳,为自己设立一个高度聚集的精神内核,内核之上可以去尝试一切有利于自己更好的方式 以上就是我个人对生活的理解,共勉
点赞 评论 收藏
分享
评论
8
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务