很好的一道dp题
首先可以推算出一行之中放n个最大m时的方案数为C(n+m-1,n)
设dp[n]表示n行的方案数 首先第一行 的第一个数应该是最小的 第一行的其他数是任意的 所以这一行取j个数时 的方案为C(n-1,j) * dp[n-j-1] (下面一行遵从同意的规则)
当时做的时候脑子抽了 写了个dfs以为是n²的 结果T了 调试了半天 才发那是n!的(>﹏<)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cctype>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<algorithm>
#include<set>
#define scnaf scanf
#define cahr char
#define bug puts("bugbugbug");
using namespace std;
typedef long long ll;
const int mod=1000000007;
const int maxn=101000+50;
const int maxe=200000;
ll fac[maxn], inv[maxn],ans;
int n,m,X[1005]={1},Y[1005]={1},a[1005];
ll powMod(ll a, ll b){
ll ans=1;
while(b)
{
if(b&1)
ans=ans*a%mod;
a=a*a%mod;
b>>=1;
}
return ans;
}
void init_c()
{
int maxn=101000;
fac[0]=1;
for(int i=1; i<=maxn; i++)
fac[i]=fac[i-1]*i%mod;
inv[maxn]=powMod(fac[maxn],mod-2);
for(int i=maxn-1; i>=0; i--)
inv[i]=inv[i+1]*(i+1)%mod;
}
int c(int n,int m){
return fac[n]*inv[m]%mod*inv[n-m]%mod;
}
inline void RDF(int &ret) { //输入为负数
char c;
int sgn;
while(c != '-' && (c < '0' || c > '9')) c = getchar();
sgn = (c == '-') ? -1 : 1;
ret = (c == '-') ? 0 : (c - '0');
while(c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c - '0');
ret *= sgn;
}
inline void RD(int &ret) { //输入为整数
char c;
do {
c = getchar();
} while(c < '0' || c > '9');
ret = c - '0';
while((c = getchar()) >= '0' && c <= '9') {
ret = ret * 10 + (c - '0');
}
}
inline void OT(int a) { //输出为正数
if(a >= 10) {
OT(a / 10);
}
putchar(a % 10 + '0');
}
int T_T,test=1;
ll dp[1005];
void print(){
putchar('C');putchar('a');putchar('s');putchar('e');putchar(' ');putchar('#');
OT(test++); putchar(':');putchar(' '); OT(ans);putchar('\n');
}
int main()
{
init_c();
RD(T_T);
while(T_T--){
ans=0;
RD(n);RD(m);
for(int i=1;i<=n;i++){
X[i]=c(i+m-1,i);
}
dp[0]=1;
for(int i=1;i<=n;i++){
dp[i]=0;
for(int j=0;j<=i-1;j++)
dp[i]=(dp[i]+c(i-1,j)*dp[i-1-j]%mod*X[j+1])%mod;
}
ans=dp[n];
print();
}
return 0;
}