- https://ac.nowcoder.com/acm/contest/139/E
- 题意:一个数组s,长度为n(n≤105)n≤105),数组元素s[i]≤10s[i]≤10, 要求从中删除m(m≤10)m≤10)个数字。
- 求能得到多少个不重复的结果, mod 1e9+7
- 思路:dp[i][j] =前i个数字删除j个后有多少种结果,转移方程为dp[i][j] = dp[i-1][j-1] + dp[i-1][j]。(j<=i&&j<=m)即可
- (不可以忽略掉j==i时,前i-1个中无法删去j,因为这时dp[i-1][j]不合法为0无影响,并且dp[i-1][j-1]中有合法状态)
- 方程含义为:前i-1个数字中删除j-1个再删除第i个数字, 和 前i-1个中删除j个,在题意要求下会有重复
- 例如{1, 2, 3, 1, 2}删除3个数字得到{1,2}与{ 1, 2}删0个是一样的,删除两个相同数字之间的所有数字加这两个数字中的一个。
-
#include<bits/stdc++.h> using namespace std; const int mod=1000000007; #define maxn 123456 int pre[maxn],head[15]; int n,m,k,dp[maxn][15],a[maxn]; int main() { while(~scanf("%d%d%d",&n,&m,&k)) { memset(dp,0,sizeof(dp)); memset(pre,0,sizeof(pre)); memset(head,0,sizeof(head)); for(int i=1; i<=n; i++) { scanf("%d",&a[i]); pre[i]=head[a[i]]; head[a[i]]=i; } dp[0][0]=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]; if(pre[i]&&j>=i-pre[i]) dp[i][j]-=dp[pre[i]-1][j-(i-pre[i])]; dp[i][j]%=mod; dp[i][j]+=mod; dp[i][j]%=mod; } } printf("%d\n",dp[n][m]); } return 0; }