输出答案对1e9+7取模

样例输入
5 10
样例输出
14
分析:这是一道动态规划题,设f[i][j][k]表示走到了第i个位置,遇到了j个花,还剩k斗酒的合法方案数.

初始化很简单就是f[0][0][2]=1,因为一开始酒的数量是2

假如共遇到店n次,遇到花m次:

那么答案就是f[n+m-1][m-1][1]
,这是很容易理解的,因为我们共需要遇到m次花且最后一次一定是花,则走到倒数第二个位置时一定已经遇到了m-1个花,且由于遇到花后酒的数量会减少1,所以走到倒数第二个位置时酒的数量也必须是1.

下面开始进行状态转移方程的推导:

首先我们有必要对酒的奇偶性进行讨论,因为当走到第i个位置时酒的数量为偶,则第i个位置不可能为店,因为无论是奇数还是偶数,乘以2得到的数都是一个偶数,所以只有当k是偶数时第i个位置才可能是店,假如第i个位置是店,那么这个时候在第i-1个位置的酒的数量就是k/2,而遇到花的数量跟第i-1个位置是一样的都是j,这个很好理解,下面再看一下第i个位置是花的情况,那么第i-1个位置的酒的数量一定是k+1,因为在第i个位置消耗了1,而到达第i个位置遇到的花的数量就要比第i-1个位置遇到花的数量多1,因为我们现在是在假设第i个位置是花。

这就是这道题目的全部分析过程了,下面给出代码:
#include<iostream> #include<algorithm> #include<cstdio> #include<cstring>
#include<set> #include<vector> #include<map> #include<queue> using namespace
std; const int N=113; const int mod=1e9+7; long long
f[N*2][N][N];//f[i][j][k]表示走到了第i个位置,遇到了j个花,还剩k斗酒的合法方案数 int main() {
f[0][0][2]=1;//初始化 int n,m; cin>>n>>m; for(int i=1;i<n+m;i++) for(int
j=0;j<m;j++) for(int k=0;k<=m;k++)//酒的数量不能超过花的数量,否则就算之后一直是花也喝不完 {
if(!(k&1))//k是偶数,则第i个位置可以是店,否则不可以是店
f[i][j][k]=(f[i][j][k]+f[i-1][j][k>>1])%mod; if(j>=1)//无论k是奇数还是偶数,第i个位置都可以是花
f[i][j][k]=(f[i][j][k]+f[i-1][j-1][k+1])%mod; }
printf("%lld",f[n+m-1][m-1][1]); return 0; }

技术
下载桌面版
GitHub
百度网盘(提取码:draw)
Gitee
云服务器优惠
阿里云优惠券
腾讯云优惠券
华为云优惠券
站点信息
问题反馈
邮箱:[email protected]
QQ群:766591547
关注微信