每日一题Day5
题解:
dp题目但是还是太菜了...
我们定义状态函数为前
i
个元素中删去j
个元素后得到的子序列数目,如果不考虑重复,就有。但是这样转移的话会有重复序列的情况出现,比如
1 2 1
序列,删除和删除
是一样的结果。那么我们发现,出现重复的情况的前提是**当前元素
有重复元素且两者之间的元素和其中一个
全部被删除。**
于是可以更新一下转移方程:其中
past
是上一次出现的位置。
AC代码:
#define _CRT_SECURE_NO_WARNINGS #pragma warning(disable:4996) #include<bits/stdc++.h> #define ll long long #define INF 0x3f3f3f3f #define inf -0x3f3f3f3f #define me(a,b) memset(a,b,sizeof(a)) #define PII pair<int,int> #define ull unsigned long long #define ios std :: ios :: sync_with_stdio(false) #define rep(i,a,b) for(int i = a;i <= b;i ++) #define esp 1e-16 using namespace std; const int maxn = 1e5 + 9; const int mode = 1e9 + 7; ll dp[maxn][12] = {}; int n, m, k; int a[maxn] = {}, pre[maxn] = {}; int main() { ios; while (cin >> n >> m >> k) { me(dp, 0); me(pre, -1); rep(i, 1, n) cin >> a[i]; dp[0][0] = 1; rep(i, 1, n) { dp[i][0] = 1; rep(j, 1, min(m, i)) { dp[i][j] = (dp[i - 1][j] + dp[i - 1][j - 1] + mode) % mode; if (pre[a[i]] != -1 && (i - pre[a[i]]) <= j) dp[i][j] = (dp[i][j] - dp[pre[a[i]] - 1][j - (i - pre[a[i]])] + mode) % mode; } pre[a[i]] = i; } cout << dp[n][m] << endl; } return 0; }