AtCoder Regular Contest 068 F - Solitaire

arc068f
http://www.elijahqi.win/2017/12/27/atcoder-regular-contest-068-f-solitaire/
题目也简称arc068f啦啦
F - Solitaire

Time limit時間制限 : 2sec / Memory limitメモリ制限 : 256MB

配点 : 1200 点
問題文

すぬけくんは N 枚のカードとデック(両端キュー)で遊ぶことにしました。 カードには 1,2,3…,N の数が書かれており、デックははじめ空です。

すぬけくんは 1,2,3,…,N が書かれたカードをこの順に、それぞれデックの先頭あるいは末尾に挿入します。 その後、すぬけくんはデックの先頭あるいは末尾からカードを取り出して食べる、という操作を N 回行います。

食べたカードに書かれていた数を食べた順番に並べて数列を作ることにします。このようにして作ることが可能な数列のうち、K 番目の要素が 1 であるようなものの個数を 109+7 で割った余りを求めなさい。
制約

1≦K≦N≦2,000

入力

入力は以下の形式で標準入力から与えられる。

N K

出力

答えを出力せよ。
入力例 1
Copy

2 1

出力例 1
Copy

1

条件を満たす並びは 1,2 の 1 通りです。例えば以下のようにして、この並びを構成することが可能です。

1,2 のどちらもカードの山の一番下に挿入する
カードの山の一番上からカードを取り出して食べることを 2 回行う

入力例 2
Copy

17 2

出力例 2
Copy

262144

入力例 3
Copy

2000 1000

出力例 3
Copy

674286644

Score : 1200 points
Problem Statement

Snuke has decided to play with N cards and a deque (that is, a double-ended queue). Each card shows an integer from 1 through N, and the deque is initially empty.

Snuke will insert the cards at the beginning or the end of the deque one at a time, in order from 1 to N. Then, he will perform the following action N times: take out the card from the beginning or the end of the deque and eat it.

Afterwards, we will construct an integer sequence by arranging the integers written on the eaten cards, in the order they are eaten. Among the sequences that can be obtained in this way, find the number of the sequences such that the K-th element is 1. Print the answer modulo 109+7.
Constraints

1≦K≦N≦2,000

Input

The input is given from Standard Input in the following format:

N K

Output

Print the answer modulo 109+7.
Sample Input 1
Copy

2 1

Sample Output 1
Copy

1

There is one sequence satisfying the condition: 1,2. One possible way to obtain this sequence is the following:

Insert both cards, 1 and 2, at the end of the deque.
Eat the card at the beginning of the deque twice.

Sample Input 2
Copy

17 2

Sample Output 2
Copy

262144

Sample Input 3
Copy

2000 1000

Sample Output 3
Copy

674286644

感觉这题还挺数学的呢 还是leoly强啊 强%%

题意:每次从1~n往两边加数 每次 取的时候从两边取问第k个是1的情况 一共有多少是成立的

首先 我们可以通过观察得出 我1~n加数的这个数列 一定是一个v字形的这么一个序列 然后1在最中间 那么这样的话 我取到1的话是不是说明我前面的k-1一定可以是一个降序序列或者是两个降序序列 那么求一下这个个数我可以dp一下 设f[i][j]表示我已经填了前1~i这么多个位置了 我前面填过的数中最小的是j那我可以知道我现在其实是假设有两个栈 然后分别取数的方案数 比如 我取9 8 7 2

这样 如果下一个数一定要比我大的话 方案数 必须只能转移到当前空缺位置 的最大 否则就是无效的

或者可以选择转移到所有比我小的地方 累积一下方案数

相当于我这个dp要求这样的 有多少个 那么f[i+1][j]自然可以由上一层的f[i][j+1]+f[i+1][j+2]+….得到啊 然后针对这个做一个前缀和优化 变成n^2的情况然后转移的时候要注意一些细节 比如如果k是0的情况

然后那么只要前面k个都确定了 剩下的我是不是还是随便选啦 可以当作是dp 就是每次从两边选一个的方案数一共是多少 那么前面k个确定了 后面我随便放 方案数就是2^(n-k-1)种方案数 为什么呢 因为这次一定剩下的是一条递增的序列了 我想怎么取就怎么取

最后统计答案的时候我只需要把前k-1位的所有情况都取出来 然后后n-k让他随便排 乘一乘就好

#include<cstdio>
#include<algorithm>
#define N 2200
#define mod 1000000007
using namespace std;
int f[N][N],s[N],n,k,ans;//设f[i][j]表示已经选取了1~i个位置 最小的那个数是j的方案数 
int main(){
    //freopen("arc.in","r",stdin);
    scanf("%d%d",&n,&k);f[0][n+1]=1;s[n+1]=1;
    for (int i=n;i>=1;--i) s[i]=s[i+1]+f[0][i];
    for (int i=1;i<=k-1;++i){
        for (int j=1;j<=n-i+1;++j) f[i][j]=s[j];
        s[n+1]=f[i][n+1];for (int j=n;j>=1;--j) s[j]=(s[j+1]+f[i][j])%mod;
    }for (int i=2;i<=n+1;++i) (ans+=f[k-1][i])%=mod;
    for (int i=1;i<=n-k-1;++i) (ans*=2)%=mod;printf("%d",ans);
    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值