1037: [ZJOI2008]生日聚会Party

50 篇文章 0 订阅
21 篇文章 0 订阅

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

对于100%的数据, n , m ≤ 150,k ≤ 20。


题解:

首先,冒出来是dp,然而,发现我的方程和题解不一样。。。

dp[i][j][a][b]中,i表示目前搞定i个人,j表示放进来多少男孩,a表示从后往前最多男孩比女孩多a个,b表示从后往前最多女孩比男孩多b个。(因为在末端加入孩子,对中间男女数量之差没有影响)

code:(粘了别人的)

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std ;
#define inf 0x7fffffff
#define mod 12345678
int n , m , k , f [ 301 ] [ 151 ] [ 21 ] [ 21 ] ;
int main ( )
{
     scanf ( "%d%d%d" , &n , &m , &k ) ;
     f [ 0 ] [ 0 ] [ 0 ] [ 0 ] = 1 ;
     for ( int i = 0 ; i < n + m ; ++ i )
         for ( int j = 0 ; j <= n ; ++ j )
             for ( int x = 0 ; x <= k ; ++ x )
                 for ( int y = 0 ; y <= k ; ++ y )
                     if ( f [ i ] [ j ] [ x ] [ y ] )
                     {
                         if ( x + 1 <= k && j + 1 <= n )
                         {
                             f [ i + 1 ] [ j + 1 ] [ x + 1 ] [ max ( y - 1 , 0 ) ] += f [ i ] [ j ] [ x ] [ y ] ;
                             f [ i + 1 ] [ j + 1 ] [ x + 1 ] [ max ( y - 1 , 0 ) ] %= mod ;
                         }
                         if ( y + 1 <= k && i + 1 - j <= m )
                         {
                             f [ i + 1 ] [ j ] [ max ( x - 1 , 0 ) ] [ y + 1 ] += f [ i ] [ j ] [ x ] [ y ] ;
                             f [ i + 1 ] [ j ] [ max ( x - 1 , 0 ) ] [ y + 1 ] %= mod ;
                         }
                     }
     int ans = 0 ;
     for ( int i = 0 ; i <= n ; ++ i )
         for ( int x = 0 ; x <= k ; ++ x )
             for ( int y = 0 ; y <= k ; ++ y )
             {
                 ans += f [ n + m ] [ i ] [ x ] [ y ] ;
                 ans %= mod ;
             }
     printf ( "%d\n" , ans ) ;
     return 0 ;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值