牛客网暑期ACM多校训练营(第一场) - E Removal (dp)

题目描述 

Bobo has a sequence of integers s1, s2, ..., sn where 1 ≤ si ≤ k.
Find out the number of distinct sequences modulo (109+7) after removing exactly m elements.

输入描述:

The input consists of several test cases and is terminated by end-of-file.
The first line of each test case contains three integers n, m and k.
The second line contains n integers s1, s2, ..., sn.

输出描述:

For each test case, print an integer which denotes the result.

示例1

输入

3 2 2
1 2 1
4 2 2
1 2 1 2

输出

2
4

备注:

* 1 ≤ n ≤ 105
* 1 ≤ m ≤ min{n - 1, 10}
* 1 ≤ k ≤ 10
* 1 ≤ si ≤ k
* The sum of n does not exceed 106.

题意:

给您n个数,让你删m个数,问你有多少种不同的序列。

POINT:

题解的做法:枚举接下来要加的数的种类。记下nxt[I][K] 代表i这个位置之后最近的k这个数。i-nxt[I][k]之间的数就是要删的

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <map>
using namespace std;
#define LL long long
const int maxn = 100000+33;
const int mod = 1e9+7;
int nxt[maxn][11];
int a[maxn];
LL dp[maxn][11];
int main()
{
    int n,m,k;
    while(~scanf("%d%d%d",&n,&m,&k)){
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        for(int i=1;i<=k;i++) nxt[n][i]=n+1;
        for(int i=n;i>=1;i--){
            for(int j=1;j<=k;j++) nxt[i-1][j]=nxt[i][j];
            nxt[i-1][a[i]]=i;
        }
        memset(dp,0,sizeof dp);
        dp[0][0]=1;
        for(int i=0;i<n;i++){
            for(int j=0;j<=m;j++){
                for(int t=1;t<=k;t++){
                    int to=nxt[i][t];
                    int del=to-i-1;
                    if(del+j<=m){
                        (dp[to][del+j]+=dp[i][j])%=mod;
                    }
                }
            }
        }
        LL ans=0;
        for(int i=0;i<=m;i++)
            (ans+=dp[n-i][m-i])%=mod;
        printf("%lld\n",ans);
 
    }
 
 
 
 
    return 0;
}

做法 2

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <map>
using namespace std;
#define LL long long
const int maxn = 100000+33;
const int mod = 1e9+7;
int a[maxn];
LL dp[maxn][11];
int main()
{
    int n,m,k;
    while(~scanf("%d%d%d",&n,&m,&k)){
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        memset(dp,0,sizeof dp);
        for(int i=0;i<=m;i++) dp[i][i]=1;
        for(int i=1;i<=n;i++){
            dp[i][0]=1;
            for(int j=1;j<=m&&j<i;j++){
                dp[i][j]=(dp[i-1][j-1]+dp[i-1][j])%mod;
                for(int k=i-1;k>=1&&i-k<=j;k--){
                    if(a[k]==a[i]){
                        dp[i][j]-=dp[k-1][j-(i-k)];
                        dp[i][j]=(dp[i][j]+mod)%mod;
                        break;
                    }
                }
            }
        }
        printf("%d\n",dp[n][m]);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/mr_treeeee/article/details/81147696