动态规划训练之十九
http://www.51nod.com/Challenge/Problem.html#problemId=1202
题目大意:
O(n)求出一个序列的本质不同的子序列个数
考虑动态规划:
dp[i]表示前i位子序列的个数
很显然如果没有本质不同的话,子序列个数等同于子集的个数就是2n-1
但关键就在于这个本质不同?怎么办?
当然考虑容斥
记vis[a[i]]表示上一次a[i]出现的位置
只要dp的时候减掉dp[vis[a[i]]-1]就减掉重复的了
code :
#include<bits/stdc++.h>
using namespace std;
#define mod 1000000007
long long dp[100055];
long long a[100055];
long long vis[100055];
int main()
{
int n, i;
while(~scanf("%d", &n))
{
for(i = 1; i <= n; i++)scanf("%lld", &a[i]);
memset(vis, 0, sizeof(vis));
memset(dp, 0, sizeof(dp));
dp[0] = 1;
for(i = 1; i <= n; i++)
{
dp[i] = (dp[i - 1]<<1) % mod;
if(vis[a[i]])
dp[i] = (dp[i] - dp[vis[a[i]] - 1] + mod) % mod,vis[a[i]] = i;
else vis[a[i]] = i;
}
printf("%lld\n", dp[n] - 1);
}
}