帮写一个这样的c++代码。把m个相同的苹果放在n个相同的盘子里,允许有的盘子空着不放,问有多少种不同的分法?用k表示511和151是同一种分法。第一行的测试数据的数目t大于10<20,以下每行均包含两个整数m和n,以空格分开。
时间: 2024-12-14 14:19:03 浏览: 30
这是一个经典的组合数学问题,可以用动态规划或者递归的方式解决。我们可以创建一个二维数组dp[m+1][n+1],其中dp[i][j]表示将i个苹果放入j个盘子的方案数。因为每个苹果都可以单独成为一个盘子,所以初始状态dp[1][1]=1。然后对于每个苹果和每个盘子,如果苹果不放,则dp[i][j]=dp[i][j-1];如果苹果放,则dp[i][j]=dp[i-1][j-1]+dp[i-1][j](相当于在剩下的苹果和盘子中选择)。最后,我们要判断两个分法是否相同,这里由于k=511和151都是二进制表示下的11111111,说明两个分法中每个位置都有一只苹果,所以只要遍历dp数组查看所有元素是否相等即可。
以下是伪代码形式:
```cpp
#include <iostream>
using namespace std;
bool isSame(int m, int n, int k) {
vector<int> bits(m + 1);
for (int i = 1; i <= m; ++i) {
if (k & (1 << (m - i))) { // 判断第i个位置是否有苹果
bits[i]++;
}
}
return bits == vector<int>(n + 1, 1); // 比较是否所有盘子都有一个苹果
}
int countWays(int m, int n) {
dp[m + 1][n + 1] = 1; // 初始化每个盘子至少有一个空的解决方案
for (int i = 1; i <= m; ++i) {
for (int j = 1; j <= n; ++j) {
dp[i][j] += dp[i - 1][j]; // 不放苹果
if (j > 0) {
dp[i][j] += dp[i - 1][j - 1]; // 放苹果
}
}
}
return dp[m][n];
}
int main() {
int t;
cin >> t;
while (t--) {
int m, n;
cin >> m >> n;
int k;
cin >> k;
bool sameDivision = isSame(m, n, k);
int ways = countWays(m, n);
cout << (sameDivision ? "是" : "否") << endl;
cout << "有 " << ways << " 种不同的分法。\n";
}
return 0;
}
```
阅读全文