牛客小白月赛101 A~E
A-tb的区间问题
题意:tb 给了 fc 一个长度为 n 的数组 A, fc 对 A 进行 k 次如下操作:
删除数组第一个元素或者删除数组最后一个元素。
求最后得到的数组和的最大值。
思路:最后删除的是某一组前后缀,一一去枚举可行的区间即可。
// AC one more times // nndbk #include <bits/stdc++.h> using namespace std; typedef long long ll; const int mod = 1e9 + 7; const int N = 2e5 + 10; ll a[N],s[N]; int main() { ios::sync_with_stdio(false); cin.tie(nullptr), cout.tie(nullptr); int n,k; cin>>n>>k; for(int i = 1;i <= n; i++) cin>>a[i]; for(int i = 1;i <= n; i++) s[i] = s[i-1] + a[i]; int len = n-k; ll ans = 0; for(int i = 1;i <= n; i++) { if(i-len+1 >= 1){ ans = max(ans,s[i]-s[i-len]); } } cout<<ans<<"\n"; return 0; }
B-tb的字符串问题
题意:tb 给了 fc 一个字符串。
fc 对字符串可以进行若干次 (可能是0) 次如下操作:
选择子串 ''fc'' 或者子串 ''tb'' ,将其从字符串中删去。
求最后剩下字符串的最短长度。
子串:原字符串中下标连续的一段字符串。
思路:能删我们肯定删呀,而且"fc"和"tb"也没有共同字母也没有干扰。我们可以用栈去维护,类似括号匹配那种。
// AC one more times // nndbk #include <bits/stdc++.h> using namespace std; typedef long long ll; const int mod = 1e9 + 7; const int N = 2e5 + 10; int main() { ios::sync_with_stdio(false); cin.tie(nullptr), cout.tie(nullptr); int n; cin>>n; string s; cin>>s; s = "?" + s; stack<char>st; for(int i = 1;i <= n; i++) { if(st.size() > 0){ char x = st.top(); char now = s[i]; if((x=='f'&&now=='c')||(x=='t'&&now=='b')) st.pop(); else st.push(now); }else st.push(s[i]); } cout<<st.size()<<"\n"; return 0; } /* 12 tfffffcccccb */
C-tb的路径问题
题意:tb 给了 fc 一张有
相邻:如果用 (x,y) 表示第 x行第 y 列的位置,(x,y) 与 (x+1,y),(x,y+1),(x−1,y),(x,y−1)(x+1,y) 相邻。
思路:我们发现对角线的数字都是每个数字第一次出现的位置,就算要瞬移也要先到这里。那么我们考虑枚举先到哪个数字,然后瞬移到距离(n,n)最近的地方,再一步步走即可。
// AC one more times // nndbk #include <bits/stdc++.h> using namespace std; typedef long long ll; const int mod = 1e9 + 7; const int N = 2e5 + 10; int main() { ios::sync_with_stdio(false); cin.tie(nullptr), cout.tie(nullptr); int n; cin>>n; ll ans = (n-1)*2; for(int i = 2;i <= n; i++) { int x = i,y = i; x = n/i*i; y = (x-1)/i*i; ll t = (i-1)*2; if(y > 0) t += (n-x)+(n-y); else t += (n-i)*2; ans = min(ans,t); // cout<<"x = "<<x<<" y = "<<y<<" t = "<<t<<"\n"; } cout<<ans<<"\n"; return 0; }
D-tb的平方问题
题意:tb 给了 fc 一个数组 A 。
随后, tb 对 fc 进行了 q 次询问,每次询问 tb 给 fc 一个 x,需要 fc 给出包含了 x 位置且区间和为完全平方数的连续子数组个数。
完全平方数:存在正整数 t ,满足
连续子数组:原数组中某段下标连续的元素按原顺序构成的数组。
思路:可以先求个前缀和,然后枚举区间,如果是完全平方数那么这段区间的贡献加1。对于区间加很容易想到差分。
// AC one more times // nndbk #include <bits/stdc++.h> using namespace std; typedef long long ll; const int mod = 1e9 + 7; const int N = 3100; int s[N],d[N],a[N]; int main() { ios::sync_with_stdio(false); cin.tie(nullptr), cout.tie(nullptr); int n,q; cin>>n>>q; for(int i = 1;i <= n; i++){ cin>>a[i]; s[i] = s[i-1] + a[i]; } for(int i = 1;i <= n; i++) { for(int j = i;j <= n; j++) { int l = i,r = j; int t = s[r]-s[l-1]; int tt = sqrt(t); if(tt*tt == t) d[l]+=1,d[r+1]-=1; } } for(int i = 1;i <= n;i++) d[i]+=d[i-1]; while(q--) { int x; cin>>x; cout<<d[x]<<"\n"; } return 0; }
E-tb的数数问题(调和级数)
题意:tb 给了 fc 一个包含若干个数字的可重集合 A ,如果我们说一个数字 x 是好的当且仅当
现在,fc 想知道有多少个不同的正整数是好的,请你告诉他吧。
d∣x : 表示 d 为 x 的约数。
思路:最后的好数一定是A里面的数(因为至少包含数本身)。g[x]=1表示x存在。我们正常的求f[x]的约数有几个,h[x]是在A里面的x的约数个数。如果f[x]==h[x]则说明都在了。这里是调和级数的复杂度
int d[1000001] = {0}; // 储存因数倍数,初始全为 0 for (int i = 1; i <= n; i++) // 枚举 [1, n] 的数 { for (int j = i; j <= n; j += i) // 枚举 i 的倍数 { d[j]++; } }
代码:
// AC one more times // nndbk #include <bits/stdc++.h> using namespace std; typedef long long ll; const int mod = 1e9 + 7; const int N = 2e6 + 10; ll a[N],f[N],g[N],h[N]; int main() { ios::sync_with_stdio(false); cin.tie(nullptr), cout.tie(nullptr); int n; cin>>n; ll mx = 0; for(int i = 1;i <= n; i++) { cin>>a[i]; mx = max(mx,a[i]); g[a[i]] = 1; } for(int i = 1;i <= mx; i++) { for(int j = i;j <= mx; j += i){ f[j]++; h[j] += g[i]; } } ll ans = 0; for(int i = 1;i <= mx; i++) ans += (f[i] == h[i]); cout<<ans<<"\n"; return 0; }
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步