牡牛和牝牛
约翰要带 $N$ 只牛去参加集会里的展示活动,这些牛可以是牡牛,也可以是牝牛。
牛们要站成一排,但是牡牛是好斗的,为了避免牡牛闹出乱子,约翰决定任意两只牡牛之间至少要有 $K$ 只牝牛。
请计算一共有多少种排队的方法,所有牡牛可以看成是相同的,所有牝牛也一样,答案对 $5000011$ 取模。
输入格式
一行,输入两个整数 $N$ 和 $K$。
输出格式
一个整数,表示排队的方法数。
数据范围
$1 \leq N \leq {10}^{5}$,
$0 \leq K < N$
输入样例:
4 2
输出样例:
6
样例解释
$6$ 种方法分别是:牝牝牝牝,牡牝牝牝,牝牡牝牝,牝牝牡牝,牝牝牝牡,牡牝牝牡。
解题思路
为了方便这里用$1$表示牡牛,用$0$表示牝牛。
最开始想到用动态规划,然后定义状态$f(i, j)$表示长度为$i$且结尾有$j$个连续的$0$的所有合法字符串的数量,状态转移方程就是
$$f(i,j) =
\begin{cases}
\sum\limits_{u = k}^{i-1}{f(i-1, u)}, \ \ &j = 0 \\\\
f(i-1, j – 1), &j > 0
\end{cases}$$
即使对状态转移的过程进行优化,时间复杂度最好也是$O(n^2)$。
然后参考了y总的状态定义,这种定义方法是真的没想到。定义状态$f(i)$表示所有长度为$i$的且以$1$结尾的合法字符串数量。根据上一个$1$出现的位置来划分状态,由于两个$1$之间至少要隔$k$个$0$,因此上一个$1$最近要从下标$i – k – 1$开始。状态转移方程就是$f(i) = 1 + \sum\limits_{j = 1}^{i – k – 1}{f(j)}$,其中$+1$是指前面均是$0$而没有$1$的情况。
可以发现每次状态转移都是关于$f(i)$的一个前缀和,因此可以开个变量来记录$f(i)$的前缀和,这样状态转移就可以降到$O(1)$,因此整个算法的时间复杂度为$O(n)$。
AC代码如下:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 const int N = 1e5 + 10, mod = 5000011; 5 6 int f[N]; 7 8 int main() { 9 int n, m; 10 cin >> n >> m; 11 for (int i = 1, s = 0; i <= n; i++) { 12 f[i] = 1; // 前面全是0的情况 13 if (i - m - 1 > 0) f[i] = (f[i] + s) % mod; // 至少要隔m个0 14 if (i - m > 0) s = (s + f[i - m]) % mod; // 累加f[i]的前缀和 15 } 16 int ret = 1; 17 for (int i = 1; i <= n; i++) { // 最后根据最后一个1出现的位置来统计答案 18 ret = (ret + f[i]) % mod; 19 } 20 cout << ret; 21 22 return 0; 23 }
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 const int N = 1e5 + 10, mod = 5000011; 5 6 int f[N]; 7 8 int main() { 9 int n, m; 10 cin >> n >> m; 11 for (int i = 1, s = 0; i <= n; i++) { 12 if (i - m - 1 > 0) s = (s + f[i - m - 1]) % mod; 13 f[i] = (f[i] + s + 1) % mod; 14 } 15 int ret = 1; 16 for (int i = 1; i <= n; i++) { 17 ret = (ret + f[i]) % mod; 18 } 19 cout << ret; 20 21 return 0; 22 }
参考资料
AcWing 1307. 牡牛和牝牛(算法提高课):https://www.acwing.com/video/717/
本文来自博客园,作者:onlyblues,转载请注明原文链接:https://www.cnblogs.com/onlyblues/p/17082146.html
今天的文章牡牛和牝牛_牝牛是什么「建议收藏」分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/55027.html