阅读体验更加
今日无聊来水水题~
点击题目标题即可跳转到对应题目上啦!
提示:前两题与牛客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了的普及组比赛了
明天又是一个文化课的屑,爪巴