zoukankan      html  css  js  c++  java
  • 2018牛客多校第一场 E-Removal【dp】

    题目链接:戳这里

    转自:戳这里

    题意:
    长度为n的序列,删掉m个数字后有多少种不同的序列。
    n<=10^5,m<=10。


    题解:
    dp[i][j]表示加入第i个数字后,总共删掉j个数字时,有多少种不同的序列。
    假设不考虑有重复的情况,dp方程为:dp[i][j]=dp[i-1][j] (第i个数字不删)+dp[i-1][j-1] (第i个数字删)。
    现在考虑重复的情况。
    如果前面有与a[i]相同的数字a[k] (k小于i),并且i-k<=j,就会产生重复。
    比如:cdeaae(用字符串举例比较方便)

    假设现在是i=6,j=4。那么我们需要dp[6][4]-dp[2][1]。
    那么为什么不是减掉dp[3][1]呢。
    因为dp[3][1]=dp[2][1]+dp[2][0],也就是说dp[3][1]还包括了删掉a[3]的状态,而如果删掉a[3],那么加入a[6]的时候就不会有重复了。所以减掉dp[2][1],就是减掉了a[3]不删除的情况。

    附ac代码:

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cmath>
     4 #include<string>
     5 #include<vector>
     6 #include<algorithm>
     7 #include<cstdio>
     8 #include<queue>
     9 using namespace std;
    10 typedef long long ll;
    11 const ll mod = 1e9 + 7;
    12 const int maxn = 1e5 + 10;
    13 const int maxx = 2 * 1e3;
    14 int nu[maxn];
    15 int pos[11];
    16 int pre[maxn];
    17 ll dp[maxn][11];
    18 int main()
    19 {
    20     int n, m, k;
    21     while(~scanf("%d %d %d", &n, &m, &k))
    22     {
    23         memset(pos, 0, sizeof(pos));
    24         memset(pre, 0, sizeof(pre));
    25         memset(dp, 0, sizeof(dp));
    26         for(int i = 1; i <= n; ++i)
    27         {
    28             scanf("%d", &nu[i]);
    29             pre[i] = pos[nu[i]];
    30             pos[nu[i]] = i;
    31         }
    32         for(int i = 1; i <= n; ++i)
    33         {
    34             dp[i][0] = 1;
    35         }
    36         for(int i = 0; i <= m; ++i)
    37         {
    38             dp[i][i] = 1;
    39         }
    40         for(int i = 1; i <= n; ++i)
    41         {
    42             for(int j = 1; j <= min(n - 1, 10); ++j)
    43             {
    44                 dp[i][j] = (dp[i - 1][j - 1] + dp[i - 1][j]) % mod;
    45                 if(pre[i] && (i - pre[i]) <= j)
    46                 {
    47                     dp[i][j] = (dp[i][j] - dp[pre[i] - 1][j - (i - pre[i])] + mod) % mod;
    48                     //j-(i-pre[i])是指在不删去重复元素pre[i]时,前面还要删除的个数
    49                 }
    50             }
    51         }
    52         printf("%lld
    ", dp[n][m]);
    53     }
    54     return 0;
    55 }
    View Code
  • 相关阅读:
    重构29-Remove Middle Man(去掉中间人)
    重构30-Return ASAP(尽快返回)
    重构26-Remove Double Negative(去掉双重否定)
    yaml语法学习3
    运行原理探究2
    SpringBoot简介 1
    SpringMVC项目所引用的一切依赖jar包和自定义设置
    2020/07/03 初始mybatis
    json数据格式字符串在java中的转移
    项目中遇到的一些异常
  • 原文地址:https://www.cnblogs.com/zmin/p/9358205.html
Copyright © 2011-2022 走看看