FZOJ 2129 子序列个数

OJ题目:click here~~

题目分析:设dp[ i ] 为前i个数的子序列的个数 , 下标从1开始。计算dp[ i ] 。第一种情况, 如果x[ i ] 与前面的数都不相同 , 则

dp[ i ] = dp[ i - 1] + dp[ i - 1] + 1 , 即 = 都把x[ i ] 放在后面 + 都不把x[ i ]放在后面 + x[ i ] 单独成一个序列。

第二种情况,如果x[ i ] 与前面某个相同,则找到下标t , 使得x [ t ] == x[ i ] 且t与i最近。那么dp [ i ] = dp[i - 1] + dp[ i - 1] - dp[t - 1] , 即 =   都把x[ i ] 放在后面 + 都不把x[ i ]放在后面 - 重复 计算的。

为什么说dp[t - 1]是重复计算的呢?看这个例子:1 2 3 2。当我们计算x[
4] 时,属于第二种情况, x[ 2] ==x[4] 。把x[4]放在后面,会有1  2 这个序列。这个序列在计算dp[ 2 ] 时有过,1 2,那么“都不把x[
i ]放在后面”里面已经加上了。这种情况总共有dp[t - 1]个,所以要减去重复的。

为什么不用加上x[ i ]单独成的序列呢?因为x[ i ] 在前面已经出现过了嘛,肯定已经算过咯。

AC_CODE

const int maxn = 1000002;
const int mod = 1000000007;
LL dp[maxn];
int pos[maxn];
int main(){
    int i , j , k , n , x;
    while(scanf("%d",&n) != EOF){
        memset(pos , -1 , sizeof(pos));
        dp[0] = 0;
        for(i = 1;i <= n;i++){
            scanf("%d",&x);
            if(pos[x] == -1) dp[i] = (2*dp[i - 1] + 1)%mod;
            else dp[i] = (2*dp[i - 1]  - dp[pos[x] - 1] + mod)%mod;
            pos[x] = i;
        }
        printf("%lld\n",dp[n]);
    }
}

FZOJ 2129 子序列个数

时间: 2024-10-14 00:51:24

FZOJ 2129 子序列个数的相关文章

fzuoj Problem 2129 子序列个数

http://acm.fzu.edu.cn/problem.php?pid=2129 Problem 2129 子序列个数 Accept: 162    Submit: 491Time Limit: 2000 mSec    Memory Limit : 32768 KB  Problem Description 子序列的定义:对于一个序列a=a[1],a[2],......a[n].则非空序列a'=a[p1],a[p2]......a[pm]为a的一个子序列,其中1<=p1<p2<..

FZUProblem 2129 子序列个数(dp)

 Problem 2129 子序列个数 Accept: 147    Submit: 432 Time Limit: 2000 mSec    Memory Limit : 32768 KB  Problem Description 子序列的定义:对于一个序列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,1

FZU 2129 子序列个数 (递推dp)

题目链接:http://acm.fzu.edu.cn/problem.php?pid=2129 dp[i]表示前i个数的子序列个数 当a[i]在i以前出现过,dp[i] = dp[i - 1]*2 - dp[pre - 1],pre表示a[i]在i之前的位置 当a[i]在i以前没有出现过,dp[i] = dp[i - 1] *2 + 1 1 //#pragma comment(linker, "/STACK:102400000, 102400000") 2 #include <a

子序列个数(fzu2129)

子序列个数 Time Limit:2000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Practice FZU 2129 Description 子序列的定义:对于一个序列a=a[1],a[2],......a[n].则非空序列a'=a[p1],a[p2]......a[pm]为a的一个子序列,其中1<=p1<p2<.....<pm<=n. 例如4,14,2,3

1202 子序列个数

1202 子序列个数 基准时间限制:1 秒 空间限制:131072 KB 子序列的定义:对于一个序列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,有些子序列可能是相同的,这里只算做1个,请输出a的不同子序列的数量.由于答案比较大,输出Mod 10^9 + 7的

51nod1202 子序列个数

看到a[i]<=100000觉得应该从这个方面搞.如果a[x]没出现过,f[x]=f[x-1]*2;否则f[x]=f[x-1]*2-f[pos[a[x]]-1];ans=f[n]-1,然后WA了 ?修改了一下f[x]=f[x-1]*2+1 否则f[x]=f[x-1]*2-f[pos[a[x]]-1];ans=f[n]; #include<cstdio> #include<cstring> #include<cctype> #include<algorithm

回文子序列个数

时间限制:2000ms 单点时限:1000ms 内存限制:256MB 描述 给定字符串,求它的回文子序列个数.回文子序列反转字符顺序后仍然与原序列相同.例如字符串aba中,回文子序列为”a”, “a”, “aa”, “b”, “aba”,共5个.内容相同位置不同的子序列算不同的子序列. 输入 第一行一个整数T,表示数据组数.之后是T组数据,每组数据为一行字符串. 输出 对于每组数据输出一行,格式为”Case #X: Y”,X代表数据编号(从1开始),Y为答案.答案对100007取模. 数据范围 

2015编程之美资格赛 回文子序列个数

时间限制:2000ms 单点时限:1000ms 内存限制:256MB 描述 给定字符串,求它的回文子序列个数.回文子序列反转字符顺序后仍然与原序列相同.例如字符串aba中,回文子序列为”a”, “a”, “aa”, “b”, “aba”,共5个.内容相同位置不同的子序列算不同的子序列. 输入 第一行一个整数T,表示数据组数.之后是T组数据,每组数据为一行字符串. 输出 对于每组数据输出一行,格式为”Case #X: Y”,X代表数据编号(从1开始),Y为答案.答案对100007取模. 数据范围 

计算子序列和是定值的子序列个数

题目如下: Counting Subsequences Time Limit: 5000 MSMemory Limit: 65536 K Description "47 is the quintessential random number," states the 47 society. And there might be a grain of truth in that. For example, the first ten digits of the Euler's const