子序列的個數(解)--【英雄會】

本題同樣來自caopengcs,只要你有興趣,每個人都可以出題(出題入口在主頁右側邊欄“貢獻題目”->“我要發佈”內),以下是題目詳情

子序列的定義:對於一個序列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的不同子序列的數量。    

輸入: 長度爲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[n] < 0)  //-1
    {
        sum[n] += M;
    }
    return sum[n];
}

//start 提示:自動閱卷起始唯一標識,請勿刪除或增加。
int main()
{
    int a[] = {1, 1, 4, 1};
    int length = sizeof(a) / sizeof(int);
    cout<<run(a, length);
    return 0;

}
//end //提示:自動閱卷結束唯一標識,請勿刪除或增加。


多多交流...o(∩_∩)o

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章