You are given two integers n and m. Calculate the number of pairs of arrays (a,b) such that:
the length of both arrays is equal to m;
each element of each array is an integer between 1 and n (inclusive);
ai≤bi for any index i from 1 to m;
array a is sorted in non-descending order;
array b is sorted in non-ascending order.
As the result can be very large, you should print it modulo 109+7.
The only line contains two integers n and m (1≤n≤1000, 1≤m≤10).
Print one integer – the number of arrays a and b satisfying the conditions described above modulo 109+7.
2 2
5
10 1
55
723 9
157557417
给n、m
要求构造两个数组a、b,满足:
1.数组长度为m,数组元素在1-n范围内
2.ai<=bi
3.a数组非降序
4.b数组非升序
问有多少种构造方法,对1e9+7取模
由条件
2.ai<=bi
3.a数组非降序
4.b数组非升序
可知
am<=bm
把b反转一下,b就变成非降序了
反转之后bm=b1,则am<=b1
把a、b数组拼接在一起
其实就变成构造一个长度为m*2的数组,数组非降序,就转化成一道简单题了
dp解法:
d[i][j]表示数组长度为i且第i位为j的方案数
则d[i][j]=sigma(d[i-1][k]),(k<=j)
->d[i][j]=d[i][j-1]+d[i-1][j]
组合数学解法:
题目相当于在n个数中选出2*m个数,每个数可以被选多次
设第i个数被选xi次
则x1+x2+...xn=2*m
逆向一下,问题就变成2*m个球丢到n个盒子里,盒子允许为空
为了方便计算,先给每个盒子都加一个球使得盒子不为空
问题就变为2*m+n个球丢到n个盒子里,盒子至少一个球
就隔板法即可,2*m+n共2*m+n-1个空隙,选出n-1个空隙把他们分成n份
因此答案为C(2*m+n-1,n-1)
或C(2*m+n-1,2*m)
#include
using namespace std;
#define int long long
const int maxm=1e3+5;
const int mod=1e9+7;
int d[25][maxm];
signed main(){
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++){
d[1][i]=1;
}
m*=2;
for(int i=2;i<=m;i++){//非降
for(int j=1;j<=n;j++){
d[i][j]=d[i][j-1]+d[i-1][j];
d[i][j]%=mod;
}
}
int ans=0;
for(int i=1;i<=n;i++){
ans+=d[m][i];
ans%=mod;
}
cout<<ans<<endl;
return 0;
}
#include
using namespace std;
#define int long long
const int mod=1e9+7;
const int maxm=1e4+5;//因为是n+2*m-1所以最大1019,如果只开1e3+5会越界
int fac[maxm];
int ppow(int a,int b){
int ans=1;
while(b){
if(b&1){
ans=ans*a%mod;
}
a=a*a%mod;
b>>=1;
}
return ans;
}
int C(int n,int m){
if(m>n||m<0)return 0;
int up=fac[n];
int down=fac[m]*fac[n-m]%mod;
return up*ppow(down,mod-2)%mod;
}
signed main(){
fac[0]=1;
for(int i=1;i<maxm;i++){
fac[i]=fac[i-1]*i%mod;
}
int n,m;
cin>>n>>m;
cout<<C(n+2*m-1,n-1);
return 0;
}