[BZOJ] 1037 [ZJOI2008]生日聚会

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 3007  Solved: 1795
[Submit][Status][Discuss]
Description
  今天是hidadz小朋友的生日,她邀请了许多朋友来参加她的生日party。 hidadz带着朋友们来到花园中,打算
坐成一排玩游戏。为了游戏不至于无聊,就座的方案应满足如下条件:对于任意连续的一段,男孩与女孩的数目之
差不超过k。很快,小朋友便找到了一种方案坐了下来开始游戏。hidadz的好朋友Susie发现,这样的就座方案其实
是很多的,所以大家很快就找到了一种,那么到底有多少种呢?热爱数学的hidadz和她的朋友们开始思考这个问题
…… 假设参加party的人中共有n个男孩与m个女孩,你是否能解答Susie和hidadz的疑问呢?由于这个数目可能很
多,他们只想知道这个数目除以12345678的余数。

Input
  仅包含一行共3个整数,分别为男孩数目n,女孩数目m,常数k。

Output
  应包含一行,为题中要求的答案。

Sample Input
1 2 1
Sample Output
1
HINT
n , m ≤ 150,k ≤ 20。

神奇的思路,自己没想到pup。。。
f[i][j][x][y]表示前i个人,有j个男生,且男生最多比女生多x个,女生最多比男生多y个

转移的时候用已知刷未知

#include <bits/stdc++.h>
#define rep(i,j,k) for(register int i=j;i<=k;i++)
#define dow(i,j,k) for(register int i=j;i>=k;i--)
#define ez(i,x) for(register int i=h[x];i;i=e[i].n)
#define MP make_pair

using namespace std;

inline int read(){
    register char ch='*';int f=1;
    while(!isdigit(ch=getchar())) if(ch=='-') f=-1;register int x=ch-'0';
    while(isdigit(ch=getchar())) x=x*10+ch-'0';
    return x*f;
}

int n,m,k;

const int MOD=12345678;

int f[305][155][21][21];

int main(){
    n=read();
    m=read();
    k=read();
    f[0][0][0][0]=1;
    rep(i,0,n+m) rep(j,0,n) rep(x,0,k) rep(y,0,k){
        if(f[i][j][x][y]){
            if(j+1<=n&&x+1<=k) (f[i+1][j+1][x+1][max(y-1,0)]+=f[i][j][x][y]%MOD)%MOD;
            if(i-j+1<=m&&y+1<=k) (f[i+1][j][max(x-1,0)][y+1]+=f[i][j][x][y]%MOD)%MOD;
        }
     }
    int ans=0;
    rep(i,0,k) rep(j,0,k) ans+=f[n+m][n][i][j],ans%=MOD;
    cout<<ans;
    return 0;   
}



posted @ 2018-06-04 14:53  GhostCai  阅读(88)  评论(0编辑  收藏  举报