您的位置:首页 > 其它

子序列的个数(解)--【英雄会】

2014-01-07 23:39 281 查看
本题同样来自caopengcs,只要你有兴趣,每个人都可以出题(出题入口在主页右侧边栏“贡献题目”->“我要发布”内),以下是题目详情

子序列的定义:对于一个序列a=a[1],a[2],......a
,则非空序列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的不同子序列的数量。

输入: 长度为n的数组1<=n<=100,数组元素0<=a[i]<=110

输出:子序列 的个数对1000000007取余数的结果(由于答案比较大,输出Mod 1000000007的结果即可)。

首先感谢cp大神,在这一题上有着巨大的帮助,因为之前理解题意的原因,一直认为测试点有问题,后来茅塞顿开,终于理解了题意;

题目中的实例有一定的特殊性,假如给的序列为{1, 1, 4, 1};

则其子序列有“1”,“4”,“1, 1”,“1, 4”,"4, 1","1, 1, 4",“1, 1, 1”,“1, 4, 1”,以及"1, 1, 4, 1"共九种;

如果这个序列没有重复数据的话,很明显这就是一个集合的问题了;

不过当出现重复的话,此时的解法就不一样了:

如果未发生重复现象,则子序列的个数随着个数的增加,其个数sum[i] = sum[i - 1] + dp[i];此时dp[i] = sum[i - 1];

若之前发生的重复现象,即exist[x] != 0;此时的dp[i]就会发生与之前出现x值重复的组合,此时dp[i] = sum[i - 1];
dp[i] -= sum[exist[x] - 1];


继续深究,贴个代码:

#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>

const int M = 1000000007;
using namespace std;

int  run(const int *a, int n) {
    int exist[111] = {0};  //判断是否存在,数组元素0<=a[i]<=110
    int dp[101] = {0};
    int sum[101] = {1};  //个数
    int x;

    for (int i = 1; i <= n; ++i)
    {
        x = a[i - 1];  //一个一个读取元素
        dp[i] = sum[i - 1];  //
        if (exist[x] != 0 )
        {
            dp[i] -= sum[exist[x] - 1];  //之前出过此值,出现重复
            if(dp[i] < 0)
                dp[i] += M;
        }
        exist[x] = i;  //记录最近出现x的下标

        sum[i] = sum[i - 1] + dp[i];  //更新子序列个数
        if (sum[i] >= M) //超限则进行-M,重新在表示范围内
        {
            sum[i] -= M;
        }
    }

    if (--sum
 < 0)  //-1
    {
        sum
 += M;
    }
    return sum
;
}

//start 提示:自动阅卷起始唯一标识,请勿删除或增加。
int main()
{
    int a[] = {1, 1, 4, 1};
    int length = sizeof(a) / sizeof(int);
    cout<<run(a, length);
    return 0;

}
//end //提示:自动阅卷结束唯一标识,请勿删除或增加。




多多交流...o(∩_∩)o
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: