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
    
    
    
  • 相关阅读:
    <摘录>如何在64位linux强制编译32位应用程序
    Ubuntu安装Java
    Mybatis学习
    Java小工具Lombok
    jenkins忘记admin密码的处理方法
    list删除元素
    ConcurrentHashMap详解
    用户登录
    SpringDemo01
    SpringBoot Eclipse 热部署
  • 原文地址:https://www.cnblogs.com/Roni-i/p/9003459.html
Copyright © 2011-2022 走看看