HYSBZ 4321 queue2

题意:
n 个沙茶,被编号 1~n。排完队之后,每个沙茶希望,自己的相邻的两人只要无一个人的编号和自己的编号相差为 1(+1 或-1)就行;
现在想知道,存在多少方案满足沙茶们如此不苛刻的条件。
题解:
①定义f[i][j]:表示前i个沙茶,有j组相邻的相差1,且i和i-1不相邻的方案数
定义g[i][j]:表示前i个沙茶,有j组相邻的相差1,且i和i-1相邻的方案数
②g[i][j]=g[i-1][j] 第i个沙茶插在了第i-1个和第i-2个之间
+g[i-1][j-1] 第i个沙茶插在了第i-1个旁边,第i-2个的另一侧
+f[i-1][j-1]*2 第i个沙茶插在了第i-1个的左右两侧(第i-1不与第i-2相邻)
③f[i][j]=g[i-1][j+1]*j 第i个沙茶落了单,干坏事,可以拆散j对,因为不能拆散第i-1个和第i-2个
+f[i-1][j+1]*(j+1) 第i个沙茶落了单,干坏事,可以拆散j+1对
+g[i-1][j]*(i-j-1) 第i个沙茶落了单,兀自玩去了,(i-1+1)-(j+1),不能拆散j对也不能在第i-1个旁边
+f[i-1][j]*(i-j-2) 第i个沙茶落了单,兀自玩去了,(i-1+1)-(j+2),不能拆散j对也不能在第i-1个旁边
④答案输出:ans=f[n][0]

#include <cstdio>
#define maxn 1010
#define Mod 7777777
#define LL long long
int n;
LL f[maxn][maxn],g[maxn][maxn];
signed main(){
        scanf("%d",&n);
        f[1][0]=1;
        for(int i=2;i<=n;i++)
                for(int j=0;j<i;j++){
                        g[i][j]=g[i-1][j];
                        if(j){
                                (g[i][j]+=g[i-1][j-1])%=Mod;
                                (g[i][j]+=f[i-1][j-1]*2)%=Mod;
                        }
                        f[i][j]=g[i-1][j+1]*j;
                        (f[i][j]+=f[i-1][j+1]*(j+1))%=Mod;
                        (f[i][j]+=g[i-1][j]*(i-j-1))%=Mod;
                        (f[i][j]+=f[i-1][j]*(i-j-2))%=Mod;
                }
        printf("%lld
",f[n][0]);
        return 0;
}

原文地址:https://www.cnblogs.com/holy-unicorn/p/9510304.html