题意:给你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;
}