【P6191 [USACO09FEB]Bulls And Cows S】题解
题目链接
题目
一年一度的展会要来临了,Farmer John 想要把 \(N\)(\(1 \leq N \leq 100,000\))只奶牛和公牛安排在单独的一行中。 John 发现最近公牛们非常好斗;假如两只公牛在这一行中靠的太近,他们就会吵架,以至于斗殴,破坏这和谐的环境。
John 非常的足智多谋,他计算出任何两只公牛之间至少要有 \(K\)(\(0 \leq K \lt N\))只奶牛,这样才能避免斗殴。John 希望你帮助他计算一下有多少种安排方法,可避免任何斗殴的的发生。John 认为每头公牛都是一样的,每头奶牛都是一样的。因而,只要在一些相同的位置上有不同种类的牛,那这就算两种不同的方法。
思路
设 \(dp_i\) 表示在位置为 \(i\) 的地方放一头公牛的方案数,则我们可以枚举前一头公牛的位置:
\[dp_i=\sum_{j=0}^{i-k-1}dp_j \]明显,可以用前缀和优化。
时间复杂度 \(O(n)\)。
总结
这道题感觉上就应该是一道dp,其实也是用到了组合数学的思想。
其实这类dp只需要想到在某个点且这个点刚好为题目所给状态即可。
Code
// Problem: P6191 [USACO09FEB]Bulls And Cows S
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P6191
// Memory Limit: 125 MB
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include
using namespace std;
#define int long long
inline int read(){int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;
ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+
(x<<3)+(ch^48);ch=getchar();}return x*f;}
#define mo 5000011
#define N 100010
//#define M
int n, m, i, j, k;
int s[N];
signed main()
{
// freopen("tiaoshi.in","r",stdin);
// freopen("tiaoshi.out","w",stdout);
n=read(); k=read();
for(i=s[0]=1; i<=n; ++i)
{
j=s[max(0ll, i-k-1)];
s[i]=s[i-1]+j; s[i]%=mo;
}
printf("%lld", s[n]);
return 0;
}