Luogu P5999 [CEOI2016]kangaroo

Posted cjoiershiina-mashiro

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Luogu P5999 [CEOI2016]kangaroo相关的知识,希望对你有一定的参考价值。

Link
转化为排列计数,要求满足下列限制的排列({a_n})的数量:
(1.a_1=s,a_n=t)
(2.forall iin(1,n),(a_i-a_{i-1})(a_{i+1}-a_i)<0)
因为出现了大小关系限制,所以考虑从小到大放数字。
(f_{i,j})表示现在放到第(i)个数,形成了(j)个连续段的方案数,同时记录(c)表示(s,t)这两个放了几个即边界放了几个。
转移的话可以把(i)独自放一段,也可以用(i)连接两个连续段,(s,t)特殊处理。
即:
(i e swedge i e t:(j-c)f_{i-1,j-1}+jf_{i-1,j+1} ightarrow f_{i,j})
(i=svee i=t:f_{i-1,j}+f_{i-1,j-1} ightarrow f_{i,j})
答案就是(f_{n,1})

#include<cstdio>
#include<iostream>
const int P=1000000007;
int n,s,t,c,f[2007][2007];
void inc(int&a,int b){a+=b-P,a+=a>>31&P;}
int mul(int a,int b){return 1ll*a*b%P;}
int main()
{
    scanf("%d%d%d",&n,&s,&t),f[1][1]=1,c=s==1;
    if(s>t) std::swap(s,t); else if(s==t) return !printf("0");
    for(int i=2;i<=n;++i)
    {
    if(i==s||i==t) ++c;
    for(int j=1;j<i;++j) i==s||i==t? (inc(f[i][j+1],f[i-1][j]),inc(f[i][j],f[i-1][j])):(inc(f[i][j+1],mul(f[i-1][j],j+1-c)),inc(f[i][j-1],mul(f[i-1][j],j-1)));
    }
    printf("%d",f[n][1]);
}

以上是关于Luogu P5999 [CEOI2016]kangaroo的主要内容,如果未能解决你的问题,请参考以下文章

Luogu4697 CEOI2011 Balloons 单调栈

Luogu P4654 [CEOI2017]Mousetrap

Luogu P4654 [CEOI2017]Mousetrap

Luogu4652 CEOI2017 One-Way Streets 树上差分

bzoj4937: [Ceoi2016]popeala

LUOGU P2476 [SCOI2008]着色方案