[Usaco2009 Feb]Bullcow 牡牛和牝牛

原题链接https://www.lydsy.com/JudgeOnline/problem.php?id=3398

容易想到的一种\(dp\)就是:设\(dp[i][j]\)表示前\(i\)头牛里面有\(j\)头牡牛的方案数,那么转移方程就是:

\[ dp[i][j]=dp[i-1][j]+dp[i-k][j-1] \]

这里解释一下为什么是\(dp[i-k][j-1]\)。因为dp数组存的是方案数,而如果第i头牛要是牡牛,那么\(i-k\)~\(i-1\)头牛都必须是牝牛,也就是只有这一种方案。但如果由\(j-k\)后面的状态转移过来,比如\(j-k+1\),那么根据方程,这个状态包含了第\(j-k\)头牛为牡牛的情况,这是不合法的情况。又因为\(j-k\)之前的牛是什么牛都无所谓,所以应该从\(j-k\)的状态转移过来。

然后你发现这样开数组会爆空间,时间也会爆。然而我们发现,第i头牛是牡牛时,我们只需要知道第\(i-k\)头牛不是牡牛的方案数即可,与前面有几头牡牛无关。那么我们换一种状态,设\(dp[i][0/1]\)表示第i头牛是牝牛/牡牛的方案数。转移方程类似:

\[ dp[i][0]=dp[i-1][0]+dp[i-1][1];\\ dp[i][1]=dp[i-k][0]; \]

时间复杂度为\(O(N)\)

#include
#include
#include
#define maxn 100010
#define mod 5000011
using namespace std;
 
inline int read(){
    register int x(0),f(1); register char c(getchar());
    while(c<'0'||'9'

转载于:https://www.cnblogs.com/akura/p/11310411.html

你可能感兴趣的:(php)