题目
n
≤
2000
n\le 2000
n≤2000
思路
首先队列里面一定是这个样子:
然后我们取完前
k
k
k 个:
发现此时相当于取两个序列然后满足其中一个最小值大于剩下数中最大值
然后发现 红色序列固定后显然剩下蓝色序列取法固定
假设前面
k
k
k个取法算出来了,剩下数的方案显然为:
2
n
−
k
−
1
2^{n-k-1}
2n−k−1
设
f
i
,
j
f_{i,j}
fi,j 表示确定最终序列前
i
i
i 个,红色序列最小值为
j
j
j 的方案数
首先假设此时取出
x
x
x
假设
x
x
x 在红的里面,显然有
f
i
,
j
=
∑
f
i
−
1
,
k
(
j
<
k
)
f_{i,j}=\sum f_{i-1,k}(j<k)
fi,j=∑fi−1,k(j<k)
如果是放蓝色,由于它的方法已经固定了,于是有
f
i
,
j
=
f
i
−
1
,
j
f_{i,j}=f_{i-1,j}
fi,j=fi−1,j
最后显然答案为
(
f
k
,
1
−
f
k
−
1
,
1
)
∗
2
n
−
k
−
1
(f_{k,1}-f_{k-1,1})*2^{n-k-1}
(fk,1−fk−1,1)∗2n−k−1
代码
#include<set>
#include<map>
#include<stack>
#include<queue>
#include<deque>
#include<cmath>
#include<cstdio>
#include<vector>
#include<climits>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define LL long long
int read(){
int f=1,x=0;char c=getchar();
while(c<'0'||'9'<c){if(c=='-')f=-1;c=getchar();}
while('0'<=c&&c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
return f*x;
}
const int MAXN=2000;
const int INF=0x3f3f3f3f;
const int Mod=(int)(1e9+7);
int Pow(int x,int y){
if(y<0) return 1;
int ret=1;
while(y){
if(y&1) ret=1ll*ret*x%Mod;
x=1ll*x*x%Mod,y>>=1;
}
return ret;
}
int f[MAXN+5][MAXN+5];
int main(){//f[i][j]:Ç°i¸ö×îСֵΪj·½°¸Êý
int n=read(),k=read();
if(k==1){
printf("%d\n",Pow(2,n-k-1));
return 0;
}
for(int i=2;i<=n;i++)
f[1][i]=1;
for(int i=2;i<=k;i++)
for(int j=n-i+2;j>=1;j--)//n-(i-1)+1=n-i+2
f[i][j]=(f[i][j+1]+f[i-1][j])%Mod;//f[i][j]=sum f[i-1][k(j<k)]+f[i-1][j]
int ans=(f[k][1]-f[k-1][1]+Mod)%Mod;
printf("%d\n",(int)(1ll*ans*Pow(2,n-k-1)%Mod));
return 0;
}