问题描述
话说大诗人李白,一生好饮。幸好他从不开车。一天,他提着酒壶,从家里出来,酒壶中有酒2斗。他边走边唱:无事街上走,提壶去打酒。逢店加一倍,遇花喝一斗。这一路上,他一共遇到店N次,遇到花M次。已知最后一次遇到的是花,他正好把酒喝光了。

(图片来源网络,侵删)
请你计算李白这一路遇到店和花的顺序,有多少种不同的可能?
注意:酒壶里没酒(0斗)时遇店是合法的,加倍时还是没酒,但是没酒时遇到花是不合法的

(图片来源网络,侵删)
输入格式
第一行包含两个整数N和M。
输出格式
输出一个整数表示答案,由于答案可能很大,输出模 1000000007的结果
样例说明
如果我们用0代表遇到花,1代表遇到店,14种顺序如下:
010101101000000 010110010010000 011000110010000 100010110010000 011001000110000 100011000110000 100100010110000 010110100000100 011001001000100 100011001000100 100100011000100 011010000010100 100100100010100 101000001010100
#include using namespace std; /* * 思路分析: * 所有可能:即N+M的排列总数 * 限制条件:①最后一次是花②遇到花,酒不能为空③最后刚好喝完 * 运行:遇到花减少一斗,遇到店加倍 * 1.状态设计:dp[i][j][k]= 合法次数 i表示酒壶中酒的斗数,j表示还未遇到的店的个数,k表示还未遇到花的个数 * 2.状态转移方程:dp[i][j][k]=(dp[2*i][j-1][k]+dp[i-1][j][k-1]) */ int N, M;//遇到店N次遇到花M次 const int n = 105; const int mod = 1e9 + 7; long long dp[n][n][n]; long long dfs(int x, int y, int z) { if (x z) return 0;//不可能出现这种情况 剪枝 if (y == 0) return x == z;//没有酒店了,返回酒数和花数相等 if (z == 1) return x == 1 && y == 0; if (dp[x][y][z] != -1)return dp[x][y][z]; dp[x][y][z] = (dfs(2 * x, y - 1, z) + dfs(x - 1, y, z - 1))%mod; return dp[x][y][z]; } int main() { scanf("%d%d", &N, &M); memset(dp, -1, sizeof(dp)); cout