bzoj4321:queue2

传送门

解法1:

膜题解,分类讨论题

考虑设\(f[i][j][0/1]\)表示填了\(i\)个数,前\(i\)个数相邻的有\(j\)对,\(i\)\(i-1\)是否相邻

然后就是对于每次插进来一个数疯狂的分类讨论去转移就行了。

其实知道状态后面的方程就不难推了,随便推推就AC了


解法2:

猜测有规律,打表。看不出规律怎么办?

oeis

然后发现有一个很小清新的递推式,抄下来就AC了

不知道怎么推,估计是容斥吧


代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
void read(int &x) {
    char ch; bool ok;
    for(ok=0,ch=getchar(); !isdigit(ch); ch=getchar()) if(ch=='-') ok=1;
    for(x=0; isdigit(ch); x=x*10+ch-'0',ch=getchar()); if(ok) x=-x;
}
#define rg register
const int maxn=1010,mod=7777777;
int n,m,f[maxn][maxn][2];
int mul(int x,int y){return 1ll*x*y-1ll*x*y/mod*mod;}
int add(int x,int y){return x+y>=mod?x+y-mod:x+y;}
int del(int x,int y){return x-y<0?x-y+mod:x-y;}
int main(){
    read(n),f[1][0][0]=1;
    for(rg int i=2;i<=n;i++)
        for(rg int j=0;j<i;j++){
            f[i][j][1]=add(add(f[i-1][j][1],f[i-1][j-1][1]),mul(f[i-1][j-1][0],2));
            f[i][j][0]=add(mul(j,f[i-1][j+1][1]),mul(i-1-j,f[i-1][j][1]));
            f[i][j][0]=add(f[i][j][0],add(mul(j+1,f[i-1][j+1][0]),mul(i-2-j,f[i-1][j][0])));
        }
    printf("%d\n",f[n][0][0]);
}
posted @ 2019-06-20 18:15 蒟蒻--lichenxi 阅读(...) 评论(...) 编辑 收藏