fzuoj Problem 2129 子序列个数

http://acm.fzu.edu.cn/problem.php?pid=2129

Problem 2129 子序列个数

Accept: 162    Submit: 491
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,13,14,1,2,3的子序列。

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

 Input

输入包含多组数据。每组数据第一行为一个整数n(1<=n<=1,000,000),表示序列元素的个数。

第二行包含n个整数a[i] (0<=a[i]<=1,000,000)表示序列中每个元素。

 Output

输出一个整数占一行,为所求的不同子序列的个数。由于答案比较大,请将答案mod 1000000007。

 Sample Input

4
1 2 3 2

 Sample Output

13

 Hint

其中40%数据点1<=n<=1000。

 Source

福州大学第十届程序设计竞赛

分析:

给定一个字符串,求出该字符串有多少个不同的子序列

定义dp[k]为前k个字符中子序列的个数

那么dp[k]来自于两种状态,

dp[k]=2*dp[k-1]+1;如果a[k]与前k-1个字符都不相同

dp[k]=2*dp[k-1]-dp[t-1],如果a[k]与前k-1个字符有相同的,t是与之相同的最近的一个下标。

AC代码:

 1 #include<stdio.h>
 2 #include<iostream>
 3 #include<algorithm>
 4 #include<string.h>
 5 #define N 1000050
 6 #define mod 1000000007
 7 using namespace std;
 8 int a[N],b[N];
 9 long long dp[N];
10 int main()
11 {
12     int n,i,j;
13     while((scanf("%d",&n))!=EOF)
14     {
15         for(i=1;i<=n;i++)
16             scanf("%d",&a[i]);
17         memset(b,0,sizeof(b));
18         memset(dp,0,sizeof(dp));
19         for(i=1;i<=n;i++)
20         {
21             if(b[a[i]]==0)
22                 dp[i]=(dp[i-1]*2+1)%mod;
23             else
24                 dp[i]=(dp[i-1]*2-dp[b[a[i]]-1]+mod)%mod;
25             b[a[i]]=i;
26         }
27         printf("%lld\n",dp[n]%mod);
28     }
29     return 0;
30
31 }
时间: 2024-12-23 18:38:19

fzuoj Problem 2129 子序列个数的相关文章

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

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

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

hdu4632 Palindrome subsequence 回文子序列个数 区间dp

Palindrome subsequence Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/65535 K (Java/Others)Total Submission(s): 4513    Accepted Submission(s): 1935 Problem Description In mathematics, a subsequence is a sequence that can be derived f

Codeforcecs1183H Subsequence(hard version) 求字符串本质不同子序列个数

题目链接:https://www.luogu.org/problem/CF1183H 题意:给你一个长为n(100)的字符串,你需要找出k(1e12)个它本质不同的子序列,且没找出一个子序列的花费为n-len(子序列),求最小花费 分析:很明显想让花费最小,就从长度最大的子序列开始找,就转化成找每个长度的本质不同的子序列有多少个 我们用dp[i][j]表示从第i个字符开始,长度为j的子序列个数有多少个. 直接转移的话会出现重复,比如baa,你就会找出两个ba 所以对于每一个i,我们用一个vis数

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取模. 数据范围