bzoj4321

queue2

 HYSBZ - 4321 

n 个沙茶,被编号 1~n。排完队之后,每个沙茶希望,自己的相邻的两
人只要无一个人的编号和自己的编号相差为 1(+1 或-1)就行; 
现在想知道,存在多少方案满足沙茶们如此不苛刻的条件。
Input
只有一行且为用空格隔开的一个正整数 N,其中 100%的数据满足 1≤N ≤ 1000; 
Output
一个非负整数,表示方案数对 7777777 取模。   
 
Sample Input
4
Sample Output
2
样例解释:有两种方案 2 4 1 3 和 3 1 4 2
 
sol:超有趣的dp,但自己就是想不出来,然后翻了题解
考虑把n个数字按1~n一个个填过去,而不是按照位置1~n一个个填数字

把数字按照1~n排序,
dp[i][j][0]表示用到i,有j对数相差为1,i与i-1不相邻
dp[i][j][1]表示用到i,有j对数相差为1,i与i-1相邻
题解 https://blog.csdn.net/yjschaf/article/details/72453712

/*
    把数字按照1~n排序,
    dp[i][j][0]表示用到i,有j对数相差为1,i与i-1不相邻 
    dp[i][j][1]表示用到i,有j对数相差为1,i与i-1相邻 
    题解 https://blog.csdn.net/yjschaf/article/details/72453712
*/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
inline ll read()
{
    ll s=0;
    bool f=0;
    char ch=' ';
    while(!isdigit(ch))
    {
        f|=(ch=='-'); ch=getchar();
    }
    while(isdigit(ch))
    {
        s=(s<<3)+(s<<1)+(ch^48); ch=getchar();
    }
    return (f)?(-s):(s);
}
#define R(x) x=read()
inline void write(ll x)
{
    if(x<0)
    {
        putchar('-'); x=-x;
    }
    if(x<10)
    {
        putchar(x+'0'); return;
    }
    write(x/10);
    putchar((x%10)+'0');
    return;
}
#define W(x) write(x),putchar(' ')
#define Wl(x) write(x),putchar('\n')
const ll N=1005,Mod=7777777;
ll n,dp[N][N][2];
inline void Ad(ll &x,ll y)
{
    x+=y; x-=(x>=Mod)?Mod:0;
}
int main()
{
    int i,j,k;
    R(n);
    dp[1][0][0]=1;
    for(i=2;i<=n;i++)
    {
        for(j=0;j<=i-1;j++)
        {
            Ad(dp[i][j][0],dp[i-1][j+1][0]*(j+1)%Mod);
            Ad(dp[i][j][0],dp[i-1][j+1][1]*j%Mod);
            Ad(dp[i][j][0],dp[i-1][j][0]*(i-j-2)%Mod);
            Ad(dp[i][j][0],dp[i-1][j][1]*(i-j-1)%Mod);
            
            Ad(dp[i][j][1],dp[i-1][j-1][0]*2%Mod);
            Ad(dp[i][j][1],dp[i-1][j-1][1]);
            Ad(dp[i][j][1],dp[i-1][j][1]);
        }
    }
    Wl(dp[n][0][0]);
    return 0;
}
/*
input
4
output
2
*/
View Code

 

 
posted @ 2019-07-08 19:17  yccdu  阅读(257)  评论(0编辑  收藏  举报