DP bzoj4321 queue2

问题 J: queue2
时间限制: 1 Sec 内存限制: 128 MB
题目描述
n 个沙茶,被编号 1~n。排完队之后,每个沙茶希望,自己的相邻的两
人只要无一个人的编号和自己的编号相差为 1(+1 或-1)就行;
现在想知道,存在多少方案满足沙茶们如此不苛刻的条件。
输入
只有一行且为用空格隔开的一个正整数 N,其中 100%的数据满足 1≤N ≤ 1000;
输出
一个非负整数,表示方案数对 7777777 取模。
样例输入
4
样例输出
2
样例解释:有两种方案 2 4 1 3 和 3 1 4 2

尝试自己想,列了f[i][j]表示选了前i个,有j个位置不符合,但是如何处理i和i+1的位置关系很麻烦。看题解加了一维。f[i][j][0/1]最后一维表示i和i-1是否相邻。
f[i][j][1]:+=f[i-1][j-1][0],i-1和i-2不相邻,故i放在i-1那一侧都会对答案有1的贡献。
+=f[i-1][j][1]+f[i-1][j-1][1],现在i-1和i-2相邻,如果i放在i-1和i-2相交一侧,i-1和i-2就不再相邻。反正,i-1和i-2继续相邻。
f[i][j][0]:+=f[i-1][j][1]*(i-j-1)共有i个位置,有j个位置不能选(不能拆散任何一对),i-1左右两个位置不能选,但有一个位置和那j个重了,所以剩下i-j-1个。
+=f[i-1][j][0]*(i-j-2)同理。
+=f[i-1][j+1][0]*(j+1)要拆散一对
+=f[i-1][j+1][1]*j 拆一对,但不能拆i-1和i-2

#include <cstdio>
#define mod 7777777
#define ll long long
int n;ll f[2][1105][2];
int main()
{
    scanf("%d",&n);f[1][0][0]=1;
    for(int i=2;i<=n;i++)
        for(int j=0,x=i&1;j<i;j++)
        {
            f[x][j][1]=f[x^1][j][1];
            if(j)(f[x][j][1]+=(f[x^1][j-1][1]+f[x^1][j-1][0]*2ll))%=mod;
            f[x][j][0]=(f[x^1][j][1]*(i-j-1ll)+f[x^1][j][0]*(i-j-2ll)+f[x^1][j+1][1]*j+f[x^1][j+1][0]*(j+1ll))%mod;
        }
    printf("%lld\n",f[n&1][0][0]%mod);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值