Solution - P1370 Charlie的云笔记序列
神犇 LEMON_dasiy 推荐的题目,果然做不出来。
思路
首先定义状态 \(f_i = \sum_{j = 1}^{i} F(i,j)\)。显然 \(f_1 = 2\)(取 \(a_1\) 或 \(\emptyset\))。
然后,假设没有重复的元素,那么就有组合和单干两种选择。
- 组合:和前面的选择有关,有 \(2f_{i-1}\) 种选择(选或不选当前元素);
- 单干:取 \(a_i\) 或 \(\emptyset\)。
但是现实是,有重复。但对于一个给定的 \(a_i\),只会重复 \(dp_k+1\) 项,\(k\) 是最近的和 \(a_i\) 一样的元素。
然后求出 \(\sum dp\)。没了。
代码
#include <bits/stdc++.h>
#define rint register int
#define rllong register long long
#define llong long long
#define N 100005
using namespace std;
const int mod = (119<<23)+1;
int dp[N], lst[N];
int a[N], tmp[N], n2;
int n, ans;
int main(){
scanf("%d", &n);
for(rint i = 1; i <= n; ++i)
scanf("%d", &a[i]), tmp[i] = a[i];
sort(tmp+1, tmp+n+1), n2 = unique(tmp+1, tmp+n+1)-tmp-1;
for(rint i = 1; i <= n; ++i) a[i] = lower_bound(tmp+1, tmp+n2+1, a[i])-tmp;
dp[1] = ans = 2, lst[a[1]] = 1;
for(rint i = 2; i <= n; ++i){
dp[i] = (dp[i-1]*2+2)%mod;
if(lst[a[i]]) dp[i] = ((dp[i]-dp[lst[a[i]]-1]-1)%mod+mod)%mod;
ans = (ans+dp[i])%mod;
lst[a[i]] = i;
}
printf("%d", ans);
return 0;
}

浙公网安备 33010602011771号