由于本质不同的约束条件,我们只需要考虑字典序最小的序列。而字典序最小的序列一定长成这样
1,2,1,2,3,2,3,...,m−1,m,m−1,m
或者
1,2,1,2,3,2,3,...,m−1,m,m−1
第一种可以看成是 1,2,3,...,m 插入若干个 (i,i+1) 形成,第二种可以删去最后一个 m−1 ,看成是序列长度为 n−1 的第一种。于是我们枚举最大值 m ,只需要解决计算第一种方案的个数。
我们还剩下
#include<cstdio>
#include<algorithm>
using namespace std;
#define LL long long
const int maxn=4000010,p=1000000007;
int fac[maxn],inv[maxn],n,m;
int pow(int base,int k)
{
int ret=1;
for (;k;k>>=1,base=(LL)base*base%p)
if (k&1) ret=(LL)ret*base%p;
return ret;
}
int c(int n,int k)
{
if (k>n) return 0;
return (LL)fac[n]*inv[k]%p*inv[n-k]%p;
}
int inc(int x,int y)
{
x+=y;
return x>=p?x-p:x;
}
int main()
{
int mx,ans=1;
scanf("%d%d",&n,&m);
if ((LL)n*m==0)
{
printf("0\n");
return 0;
}
m=min(n,m);
mx=(n-m)/2+m-1;
fac[0]=inv[0]=1;
for (int i=1;i<=mx;i++) fac[i]=(LL)fac[i-1]*i%p;
inv[mx]=pow(fac[mx],p-2);
for (int i=mx-1;i>=1;i--) inv[i]=(LL)inv[i+1]*(i+1)%p;
for (int i=2;i<=m;i++)
ans=inc(ans,inc(n-1-i>=0?c((n-1-i)/2+i-1,i-1):0,c((n-i)/2+i-1,i-1)));
printf("%d\n",ans);
}