阅读体验更加

今日无聊来水水题~

点击题目标题即可跳转到对应题目上啦!

提示:前两题与牛客IOI周赛20-普及组无关,也无相应代码。想看题解的童鞋请直接跳过前面两道

P6832 Cnoi2020 子弦

大致思路:

既然让统计任意长度的子串的数量,当然是子串长度最短时取得最优解。于是直接统计字符串里每个字母都出现了几次就好,取最大值。


PP7106 双生独白

大致思路:

求反色,就是用十六进制下的 减去当前的 值。
如果你想着转换进制来做那可就太麻烦了!
如果我们再稍微看一看就会发现,反色的每一位都和正色的每一位有着对应的关系。
设反色每一位为 ,正色的每一位为
不难得出

一道屑题罢了


NC213387 完全数

大致思路:

非常水的一道题,鉴于数据范围,我们可以直接从 枚举到

暴力便是一种非常优美的解法。最高复杂度也就只有

具体实现:

#include<bits/stdc++.h>
#define int long long
signed main(void){
    int a;
    scanf("%lld",&a);
    int x = sqrt(a);
    int sum = 1;
    for(int i=2;i<=x;++i)
        if(a%i==0)sum+=(i+(a/i));
    if(sum<a)printf("Early\n");
    else if(sum>a)printf("Late\n");
    else printf("Pure\n");
    return 0;
}

NC213388 移动撤销

大致思路:

这道题你会用到一个很好玩的数据结构 deque , 几乎和 queue 一样的无脑操作。

当然肯定也会有栈党。

这两种数据结构基本上没什么区别,这题数据范围也不大。常数也非常接近……

所以,怎么舒服怎么来咯~

具体实现:

#include<bits/stdc++.h>
using namespace std;
deque<char>q;
int n,x,y;
char opt;
int main(void){
    scanf("%d",&n)
    for(int i=1;i<=n;++i){
        cin>>opt;
        if(opt!='Z'){
            q.push_back(opt);
            if(opt=='A')x-=1;else if(opt=='W')y+=1;
            else if(opt=='S')y-=1;else if(opt=='D')x+=1;
        }
        else
            if(!q.empty()){
                opt = q.back();q.pop_back();
                if(opt=='A')x+=1;else if(opt=='W')y-=1;
                else if(opt=='S')y+=1;else if(opt=='D')x-=1;
            }
    }
    printf("%d %d\n",x,y);
    return 0;
}

NC213389 石头剪刀布

大致思路:

两个人石头剪刀布,肯定尽量让布包石头,剪刀破布啊。

我们可以分为两部分来计算:

赢的:

在计算完赢的情况后,记得把对应石头剪刀布的数量减去已经统计了的

然后,大体上看上去相似的式子再算一次就好

平局的:

具体实现:

#include<bits/stdc++.h>
using namespace std;
inline char gc(){
    static char buf[1000000],*p1 = buf,*p2 = buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;
}
inline int read(){
    int ans = 0;bool f = 1;char ch = gc();
    while(ch<'0'||ch>'9'){if (ch=='-')f = 0;ch = gc();}
    while(ch>='0'&&ch<='9'){
        ans = (ans<<3)+(ans<<1)+(ch^48);
        ch = gc();
    }
    return f?ans:~(ans-1);
}
int a,b,c,x,y,z,q,w,e,ans = 0;
signed main(void){
    int n = read();
    a = read();b = read();c = read();
    x = read();y = read();z = read();
    q = min(a,y),w = min(b,***(c,x);
    a-=q,y-=q;
    b-=w,z-=w;
    c-=e,x-=e;
    ans+=q*2+w*2+e*2;
    printf("%d",ans+min(a,x)+min(b,y)+min(c,z));
    return 0;
}

NC213483 夹缝中求和

大体思路:

比赛时候卡了我挺久 (我太菜了) ,实际上就是一道考察双指针的题目。

应该是有两种移动指针的方式

第一种:比较屑,是我这种蒟蒻拿来混AK的写法,就是将 数组排序后遍历每一个 ,移动 ,找到与后方数组里恰好可以满足 的区间,然后直接统计 就好。

第二种:将数组排序后,选定一个 ,那么 的范围就可以是 的区间内。当从 枚举 时, 不断递减,统计 即可。

具体实现:

是非常屑的第一种做法

#include<bits/stdc++.h>
#define int long long
using namespace std;
inline char gc(){
    static char buf[1000000],*p1 = buf,*p2 = buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;
}
inline int read(){
    int ans = 0;bool f = 1;char ch = gc();
    while(ch<'0'||ch>'9'){if (ch=='-')f = 0;ch = gc();}
    while(ch>='0'&&ch<='9'){
        ans = (ans<<3)+(ans<<1)+(ch^48);
        ch = gc();
    }
    return f?ans:~(ans-1);
}
int bz[200000],num[200000];
signed main(void){
    int n,x,y,ans = 0;
    n = read(),x = read(),y = read();
    for(int i=1;i<=n;++i)bz[i] = read();
    int cnt = 0;
    for(int i=1;i<=n;++i)
                if(bz[i]>=y)continue;
                else num[++cnt]=bz[i];
    sort(num+1,num+cnt+1);
    int a = 2,b = cnt;
    for(int i=1;i<cnt;++i){
        a = i+1;
        while(num[a]+num[i]<x)a++;
        while(num[b]+num[i]>y)b--;
        if(a>b)break;
        ans+=b-a+1;
    }
    printf("%lld\n",ans);
    return 0;
}

好了,今天的水题就到这里了,好水啊!牛客这场算是我为数不多AK了的普及组比赛了
明天又是一个文化课的屑,爪巴