菜鸡一个,写一些网上找不到的oj叭,造福一下下一届
题目描述
n个积木,分成m垛,这些积木垛排成一行,使得所有垛的积木块数不相同,且呈“山“字形(积木数先单调上升,再单调下降)。比如6块积木,分成3垛,只有132,231两种方案。 现在已知n,m,请求方案数。
输入
第一行是一个整数T(1≤T≤1000),表示样例的个数。
以后每行两个整数n(3≤n≤100),m(3≤m≤10)。
输出
每行是输出一个样例的个数。
样例输入
2 6 3 9 3
样例输出
2 6
样例解释
第二个样例,分别为”162”,”153”,”243”,”261”,”351”,”342”。
相信做到这题的话Blocks应该已经做过了,这题其实就是在Blocks上用了一点点数学的思想。不多说了,放代码,代码风格有点丑(见谅)
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<bits/stdc++.h>
using namespace std;
int main() {
int t;
int i, j, k, l, n, m,sum;
scanf("%d", &t);
while (t--) {
int a[101][11][110];//a[i][j][k]为i块积木,共j列,第一列为k个方块的方案数
memset(a, 0, sizeof(a));
a[1][1][1] = 1;
scanf("%d %d", &n, &m);
for (i = 2; i <= n; i++) {
for (j = 1; j <= m; j++) {
for (k = 1; k <= i; k++) {
if (i == k && j == 1) { //如果排成一列,第一列为总积木时,只有一种情况
a[i][j][k] = 1;
} else {
for (l = k - 1; l >= 1; l--) {
a[i][j][k] += a[i - k][j - 1][l];
}
}
}
}//排几列
}
sum = 0;
for (i = 1; i <= n; i++) {
sum += a[n][m][i];
}
sum=sum*(pow(2,m-1)-2);
printf("%d\n", sum);
}
return 0;
}
相比于Block那道题,我只是加了一个
sum=sum*(pow(2,m-1)-2);
这里就是和积木Ⅰ不一样的地方,因为单调性要分布两边,相当于把已经搭好的积木排列组合,除了最高的一列, 每一列可以在前面或者后面,相当于X2,所以就是2^(m-1),再减去两种单调的情况。
还是谢大放水了hhh