AT2301题解
这是一个线性的做法
称一个序列是
不难发现,一个双端队列可以由操作得到当且仅当它从开头到
当这个排列的前
因此我们可以先统计合法的序列中后
根据大小关系,这等价于求第
对于一个排列,由
考虑
考虑转移
若
若
综上
最终答案就是
再推演下,当
发现这是经典的走格子
类似卡特兰数的推导,首先总路径显然为
超过
对于一种不合法的行走方案,将其第一次和
综上
答案为
复杂度
code
#include<bits/stdc++.h>
using namespace std;
const int mod=1e9+7,N=3e6+5;
int pw[N<<1],fac[N<<1],fiv[N<<1];
inline int add(int x,int y){return x+y>=mod?x+y-mod:x+y;}
inline int dec(int x,int y){return x-y<0?x-y+mod:x-y;}
inline int qpow(int x,int y)
{
int ans=1;
for(;y;y>>=1,x=1ll*x*x%mod)
if(y&1)ans=1ll*ans*x%mod;
return ans;
}
inline void pre(int n)
{
pw[0]=1;for(int i=1;i<=n;++i)pw[i]=add(pw[i-1],pw[i-1]);
fac[0]=1;for(int i=1;i<=n;++i)fac[i]=1ll*fac[i-1]*i%mod;
fiv[n]=qpow(fac[n],mod-2);
for(int i=n-1;~i;--i)fiv[i]=1ll*fiv[i+1]*(i+1)%mod;
}
inline int binom(int x,int y)
{
if(y==0)return 1;
if(x<0||y<0||x<y)return 0;
return 1ll*fac[x]*fiv[y]%mod*fiv[x-y]%mod;
}
int n,m;
int main()
{
pre(4e3);
scanf("%d%d",&n,&m);
if(n==1&&m==1){puts("1");return 0;}
printf("%d\n",1ll*pw[max(0,n-m-1)]*dec(binom(n+m-3,n-2),binom(n+m-3,n))%mod);
return 0;
}