2019牛客暑期多校训练营(第九场) F Birthday Reminders(dp)

链接:https://ac.nowcoder.com/acm/contest/889/F
来源:牛客网
 

题目描述

Today is Tomori's birthday! Usually, people get many birthday wishes on social media, but Tomori has decided to hide her birthday on social media, and thus does not expect many (if any) wishes from her friends. 

Tomori has N friends. Some of the friends actually remembered her birthday! For each friend $i$, he or she will remember Tomori's birthday at time ti and give her a birthday wish at that instant (or not remember her birthday at all if ti=−1t_i = -1ti​=−1).

Some of Tomori's friends are very considerate however, and decides to remind others about her birthday. Friend i will remind friend pi about Tomori's birthday after he or she has wished her. Formally, if Friend i gave Tomori a birthday wish at time t, then he or she will remind friend pi to give Tomori a birthday wish at time t+1 (and friend pi will give her a birthday wish at time t+1 and remind friend ppip_{p_{i}}ppi​​ at time t+2 and so on, assuming that they have not already gave her a birthday wish). The sequence pi forms a permutation, i.e. each friend will be reminded by exactly one friend. Note that pi=ip_i = ipi​=i is possible, which means that the friend will not remind anyone about Tomori's birthday after sending their wish.

The day is over and at the end of the day, Tomori receives the wish from Friend i at time bib_ibi​ (if bi=−1b_i = -1bi​=−1, it means that friend i never wished her for her birthday). Note that bib_ibi​ might not be equal to tit_iti​ as he or she might be reminded by another friend at an earlier time. 

Tomori receives the wishes, but she actually can't distinguish between her friends, so she only knows the number of wishes she received at each particular time. Now, she wonders, over all possible permutations {pi}\{p_i\}{pi​}, how many possible different days she could have experienced. Two permutations p, q correspond to different days if at some point of time, the number of friends who wished Tomori was different.

 

输入描述:

The first line of input contains a single integer N (1 <= N <= 100).

The next line of input contains N space-separated integers, the i-th of which denotes ti (ti = -1 or 1 <= ti <= 100).

输出描述:

Output a single integer, the number of different days Tomori could have experienced. Since the answer might be too large, output it modulo 1000000007.

示例1

输入

复制

3
-1 2 1

输出

复制

3

说明

There are 6 possible permutations.

If p = {1, 2, 3}, then b = {-1, 2, 1}.

If p = {1, 3, 2}, then b = {-1, 2, 1}.

If p = {2, 1, 3}, then b = {3, 2, 1}.

If p = {2, 3, 1}, then b = {2, 2, 1}.

If p = {3, 1, 2}, then b = {3, 2, 1}.

If p = {3, 2, 1}, then b = {2, 2, 1}.

There are 3 distinct possible days Tomori could have experienced.

Please note that even if we have b = {1, 2, 2} with some permutation, it is considered the same as b = {2, 2, 1}, since Tomori can't distinguish between her friends.

 

 

#include <bits/stdc++.h>
using namespace std;
const int N = 205;
const int mod = 1e9 + 7;
int dp[N][N][N];
int tim[N], sum[N];
int main() {
    ios::sync_with_stdio(0);
    int n; cin >> n;
    for (int i = 1; i <= n; i++) {
        int t; cin >> t;
        if (t != -1)tim[t]++;
    }
    for (int i = 1; i < N; i++){
        sum[i] = tim[i] + sum[i - 1];
    }
    int res = 0;
    dp[0][0][0] = 1;
    for (int i = 1; i < N; i++) {
        for (int j = sum[i]; j <= n; j++) {
            for (int k = 0; k <= j; k++) {
                for (int l = max(0, k - tim[i]); l <= j - k; l++) {
                    dp[i][j][k] += dp[i - 1][j - k][l];
                    dp[i][j][k] %= mod;
                }
                if (j >= sum[N - 1] && k) {//防止状态重复计算
                    res += dp[i][j][k];
                    res %= mod;
                }
            }
        }
    }
    if (sum[N - 1] == 0) res = 1;//特判
    cout << res << "\n";
    return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值