现在的位置: 首页 > 综合 > 正文

FZU 2129 子序列个数 (动态规划)

2018年02月23日 ⁄ 综合 ⁄ 共 893字 ⁄ 字号 评论关闭

题意:子序列的定义:对于一个序列a=a[1],a[2],......a[n]。则非空序列a'=a[p1],a[p2]......a[pm]为a的一个子序列,其中1<=p1<p2<.....<pm<=n。

例如4,14,2,3和14,1,2,3都为4,13,14,1,2,3的子序列。

对于给出序列a,请输出不同的子序列的个数。(由于答案比较大,请将答案mod 1000000007)

思路:设前i个数字的子序列数为f(i)。

           1.如果第i个数字在前i个数字里都没有出现过,那么,原来i-1个数字里面的子序列也是前i个数字的子序列,总共是f(i-1),而在原来i-1个数字的子序列每个的背后加一个a[i]也是新的子序列,总共是f(i-1)个,然后最后一个数字单独也可以组成一个新的子序列,是1个,因此这时f(i)=f(i)+f(i)+1。

           2.如果第i歌数字在前面i个数字里面出现过,那么f(i)=f(i)+f(i)-f(a[i]最后一次出现的位置-1)。因为这时候,单独一个a[i]的情况已经被计算过,于是没有了+1,而往a[i]最后一次出现的位置-1加上一个a[i]的情况也已经被计算过,一次要减掉。

注意:遇到减号的时候取模时要加MOD再取模。

#include<cstdio>
#include<cstring>
#define MOD 1000000007
#define MAXN 1000005
typedef long long LL;
LL f[MAXN];
int last[MAXN],a,n;
int main()
{
	while(~scanf("%d",&n))
	{
		memset(last,0,sizeof(last));
		f[0]=0;
		for(int i=1;i<=n;++i)
		{
            scanf("%d",&a);
			f[i]=(f[i-1]<<1)%MOD;
			if(!last[a]) last[a]=i,f[i]++;
			else f[i]=(f[i]-f[last[a]-1]+MOD)%MOD,last[a]=i;
		}
		printf("%I64d\n",f[n]%MOD);
	}
	return 0;
}

抱歉!评论已关闭.