题意:
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\n",f[n][0]); return 0; }