zoukankan      html  css  js  c++  java
  • 51nod 1202 不同子序列个数 [计数DP]

    1202 子序列个数
    题目来源: 福州大学 OJ
    基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题
    收藏
    关注
    子序列的定义:对于一个序列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的结果即可。
    Input
    
    第1行:一个数N,表示序列的长度(1 <= N <= 100000)
    第2 - N + 1行:序列中的元素(1 <= a[i] <= 100000)
    
    Output
    
    输出a的不同子序列的数量Mod 10^9 + 7。
    
    Input示例
    
    4
    1
    2
    3
    2
    
    Output示例
    
    13
    

    dp[i]为前i个字符中子序列的个数
    当a[i]没有出现过的时候,dp[i] = dp[i-1]*2 + 1,因为相当于在dp[i-1]个子序列中新增一个a[i],再加上它本身。
    当a[i]出现过的时候就要去重,减去以a[i]以前出现的位置的前一位子序列的个数=dp[vis[ a[i] ] - 1],因为a[i]为结尾重复了。

    #include <bits/stdc++.h>
    using namespace std;
    #define ll long long
    const int N = 1e5+5;
    const int  mod  = 1000000007;
    
    int a[N];
    ll dp[N]; //dp[i]为前i个字符中子序列的个数
    int vis[N];
    int main()
    {
        int n;
        while(cin >> n){
            for(int i=1;i<=n;i++){
                cin >> a[i];
            }
            memset(dp,0,sizeof(dp));
            memset(vis,0,sizeof(vis));
            dp[1]=1;
            vis[a[1]]=1;
            for(int i=2;i<=n;i++){
                if(vis[a[i]]==0){
                    dp[i] = (dp[i-1]*2 + 1)%mod;
                }else{
                    dp[i] = (dp[i-1]*2 - dp[ vis[a[i]] - 1 ] + mod) % mod;
                }
                vis[a[i]]=i; //标记a[i]出现的位置
            }
            cout<<dp[n]<<endl;
        }
        return 0;
    }
            // 1 2 3 2
            //13
    
    
    
  • 相关阅读:
    Power of Cryptography
    Radar Installation
    Emag eht htiw Em Pleh
    Help Me with the Game
    89. Gray Code
    87. Scramble String
    86. Partition List
    85. Maximal Rectangle
    84. Largest Rectangle in Histogram
    82. Remove Duplicates from Sorted List II
  • 原文地址:https://www.cnblogs.com/Roni-i/p/9003459.html
Copyright © 2011-2022 走看看