zoukankan      html  css  js  c++  java
  • FZU 2129 子序列个数 (动态规划)

    题意:子序列的定义:对于一个序列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
    ",f[n]%MOD);
    	}
    	return 0;
    }
  • 相关阅读:
    PHP读写XML文件的四种方法
    如何在linux系统中设置静态ip地址
    Memcached和Memcache安装(64位win7)
    Mysql存储过程和函数区别介绍
    随笔
    Vue 中使用axios传参数,后端收不到数据
    vs2019创建mvc连接mysql
    dapper多表查询
    Java并发编程:volatile关键字解析
    Mysql Innodb 间隙锁浅析
  • 原文地址:https://www.cnblogs.com/pangblog/p/3253827.html
Copyright © 2011-2022 走看看