CodeForces1288 C.Two Arrays(dp/组合数学)

C.Two Arrays

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.

Input

The only line contains two integers n and m (1≤n≤1000, 1≤m≤10).

Output

Print one integer – the number of arrays a and b satisfying the conditions described above modulo 109+7.

Examples

input

2 2

output

5

input

10 1

output

55

input

723 9

output

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)

顺便挂个排列组合公式图:
CodeForces1288 C.Two Arrays(dp/组合数学)_第1张图片

code1:

#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;
}

code2:

#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;
}

你可能感兴趣的:(dp)