第1行:一个数N,表示序列的长度(1 <= N <= 100000) 第2 - N + 1行:序列中的元素(1 <= a[i] <= 100000)
输出a的不同子序列的数量Mod 10^9 + 7。
4 1 2 3 2
13
题解:我们知道如果不存在重复的数,那么dp[i]=dp[i-1]*2(含空集的情况)。现在考虑出现了重复的数。比如当前要取的数为a[i],且a[i]最近一次在之前的j位置出现过了。那么有dp[i]=dp[i-1]*2-dp[j-1]。所以我们利用一个数组mark记录下a[i]出现的位置就好了,没有出现过为0。
注意:在运算中会出现减的情况,所以取模是要加上mod
代码如下:
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define maxn 100010 #define mod 1000000007 long long dp[maxn]; int a[maxn]; int mark[maxn];//利用hash记录a[i]前面是否出现了一次,并记录下上一次出现的位置 int main() { int n,i,j; while(scanf("%d",&n)!=EOF) { for(i=1;i<=n;++i) scanf("%d",&a[i]); memset(dp,0,sizeof(dp)); memset(mark,0,sizeof(mark)); dp[0]=1; for(i=1;i<=n;++i) { if(mark[a[i]]==0) dp[i]=(dp[i-1]*2)%mod; else dp[i]=(2*dp[i-1]-dp[mark[a[i]]-1]+mod)%mod; mark[a[i]]=i; } printf("%lld\n",dp[n]-1); } return 0; }