BZOJ 3398 [Usaco2009 Feb]Bullcow 牡牛和牝牛:dp前缀和优化
Posted Leohh
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ 3398 [Usaco2009 Feb]Bullcow 牡牛和牝牛:dp前缀和优化相关的知识,希望对你有一定的参考价值。
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3398
题意:
约翰要带N(1≤N≤100000)只牛去参加集会里的展示活动,这些牛可以是牡牛,也可以是牝牛。
牛们要站成一排。但是牡牛是好斗的,为了避免牡牛闹出乱子,约翰决定任意两只牡牛之间至少要有K(0≤K<N)只牝牛。
请计算一共有多少种排队的方法。所有牡牛可以看成是相同的,所有牝牛也一样。答案对5000011取模。
题解:
表示状态:
dp[i] = num of ways
表示考虑到位置i,并且在这里放了牡牛的方案数。
找出答案:
ans = ∑(dp[i]) + 1
因为不放牡牛也算一种方案,所以最后+1。
如何转移:
dp[i] = ∑ dp[0 to i-k-1] + 1
上一次放牡牛的位置至少在i前面k+1个牛的位置。
或者这是第一次放牡牛,所以+1。
优化:
前缀和优化。
AC Code:
1 // state expression: 2 // dp[i] = num of ways 3 // i: last pos of cow2 4 // 5 // find the answer: 6 // sigma dp[i] + 1 7 // 8 // transferring: 9 // dp[i] = sigma dp[0 to i-k-1] + 1 10 // 11 // boundary: 12 // set dp = 0 13 #include <iostream> 14 #include <stdio.h> 15 #include <string.h> 16 #define MAX_N 100005 17 #define MOD 5000011 18 19 using namespace std; 20 21 int n,k; 22 int ans; 23 int dp; 24 int sum[MAX_N]; 25 26 void read() 27 { 28 cin>>n>>k; 29 } 30 31 void solve() 32 { 33 sum[0]=0; 34 ans=1; 35 for(int i=1;i<=n;i++) 36 { 37 dp=1; 38 if(i-k-1>=0) dp=(dp+sum[i-k-1])%MOD; 39 sum[i]=(sum[i-1]+dp)%MOD; 40 ans=(ans+dp)%MOD; 41 } 42 } 43 44 void print() 45 { 46 cout<<ans<<endl; 47 } 48 49 int main() 50 { 51 read(); 52 solve(); 53 print(); 54 }
以上是关于BZOJ 3398 [Usaco2009 Feb]Bullcow 牡牛和牝牛:dp前缀和优化的主要内容,如果未能解决你的问题,请参考以下文章
BZOJ 3398 [Usaco2009 Feb]Bullcow 牡牛和牝牛:dp前缀和优化
bzoj3398: [Usaco2009 Feb]Bullcow 牡牛和牝牛(排列组合)
bzoj1579 [Usaco2009 Feb]Revamping Trails 道路升级
bzoj1579: [Usaco2009 Feb]Revamping Trails 道路升级
Bzoj 1579: [Usaco2009 Feb]Revamping Trails 道路升级 dijkstra,堆,分层图