「解题报告」CF1178B WOW Factor
¿
这是一道非常富有启发性的题目,值得一做,闪耀着人类和机器人的智慧光辉的绝佳题目 .
首先注意到 (vv)o(vv)
的结构,可以考虑枚举中间的 o
,这样只需要算两边的选法然后用乘法原理即可 .
乘法原理:做一件事,完成它需要分成 个步骤,做第一步有 种不同的方法,做第二步有 种不同的方法,……,做第 步有 种不同的方法。那么完成这件事共有 种不同的方法 .
根据乘法原理,其实就是选择这个字符串有三个步骤,先选左边有 种,中间的 o
有 种,右边有 种,那么总方案数就是 .
那么考虑怎么求 和 ,分别考虑:
Part 1 求
厉害的一步到了,令 表示 (这里的 叫 Iverson Bracket,大佬教的, 就是 bool(x)
)
那么如果 o
的位置是 ,那么 就是连续 vv
的个数了,不用考虑冲突,因为只需要选一个不选多个 .
如果每次都直接求和,需要约 次加法,无法接受,怎么办呢?
发现是要对于每个位置求,于是假设第 个位置的答案是 ,第 个位置的答案是 (不需要考虑是否为 o
,后面说原因),那么
惊奇的发现:!
这样先算出第一个位置的答案,然后用一个 for 循环就可以求出每个位置的 值,使用时只计算有 o
的位置就行了 .
Part 2 求
也是类似的做法,如果 o
的位置是 ,那么 就是连续 vv
的个数 .
假设第 个位置的答案是 ,第 个位置的答案是 ,那么
这时候我们得到的是 ,也是先算出第一个位置的答案用一个 for 循环就可以求出每个位置的 值了 .
还可以看 ,这样从后往前 for,初始的位置就不需要再用一个 for 循环了 .
总共的时间复杂度为 ,可以 Accepted 了 . 记得开 long long
!
接下来就是简洁的代码,细节很多,要好好考虑:
const int N = 1919810;
string s;
int n, pre[N], suf[N];
int main()
{
cin >> s; n = s.length(); s = "$" + s;
for (int i=1; i<n; i++) pre[i] = pre[i-1] + ((s[i] == 'v') && (s[i+1] == 'v'));
for (int i=n-1; i>=1; i--) suf[i] = suf[i+1] + ((s[i] == 'v') && (s[i+1] == 'v'));
ll ans = 0;
for (int i=1; i<n; i++)
if (s[i] == 'o') ans += 1ll * pre[i-1] * suf[i];
printf("%lld\n", ans);
return 0;
}
可以看出题面的表述相当自然易懂,而每一步的思维却都非常跳跃,思维量很大结果却很简洁,推导答案的形式不涉及很困难的算法,却又不仅限于结论,而是巧妙地结合了 OI 知识,启发选手独自研发题目所需要的算法,为良心出题人点赞!
以下是博客签名,正文无关
本文来自博客园,作者:yspm,转载请注明原文链接:https://www.cnblogs.com/CDOI-24374/p/17189455.html
版权声明:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议(CC BY-NC-SA 4.0)进行许可。看完如果觉得有用请点个赞吧 QwQ
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】