2018牛客多校第一场E Removal(dp)

题目链接

题意:给你n个数,删除m个数之后有多少种不同的序列

思路:根据官方的题解,枚举要加的数的种类。记下Next[i][k] 代表i这个位置之后最近的k这个数。而i-Next[i][k]之间的数就是要删的,

最后还需要再扫一遍末尾几个数是否要删的情况。

代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=1e5+10;
const int mod=1e9+7;
ll dp[N][15];
int Next[N][15];
int a[N];
int main()
{
    int n,m,k;
    while(~scanf("%d%d%d",&n,&m,&k))
    {
        memset(Next,0,sizeof(Next));
        memset(dp,0,sizeof(dp));
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
        }
        for(int i=1;i<=k;i++)
        {
            Next[n][i]=n+1;
        }
        for(int i=n;i>=1;i--)
        {
            for(int j=1;j<=k;j++)
            {
                Next[i-1][j]=Next[i][j];
            }
            Next[i-1][a[i]]=i;
        }
        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=Next[i][t];
                    int z=to-i-1;
                    if(z+j<=m)
                    {
                        (dp[to][z+j]+=dp[i][j])%=mod;
                    }
 
                }
            }
        }
        ll ans=0;
        for(int i=0;i<=m;i++)
        {
            ans=(ans+dp[n-i][m-i])%mod;
        }
        printf("%lld\n",ans);
    }
    return 0;
}

还有一种方法别人的解释更好

代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=1e5+10;
const int mod=1e9+7;
int a[N];
ll dp[N][11];
int main()
{
    int m,n,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]+dp[i-1][j-1])%mod;
                for(int z=i-1;z>=1&&i-z<=j;z--)
                {
                    if(a[i]==a[z])
                    {
                        int to=i-z;
                        dp[i][j]=(dp[i][j]-dp[z-1][j-to]+mod)%mod;
                        break;
                    }
                }
            }
        }
        printf("%lld\n",dp[n][m]);

    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/imzxww/article/details/81157187