zoukankan      html  css  js  c++  java
  • 51nod 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

    思路:对于一个n个不同的数我们可以知道前i个数的不同子集(这里计算包含空集)个数为: dp[i] = 2*dp[i-1];而前方有可能有相同的数出现过,假设在前面第j个位置出现那么 dp[i] = 2*dp[i-1] - dp[j-1];所以我们需要用一个数组记录当前这个数在上一次出现的位置

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<cstdio>
     4 
     5 using namespace std;
     6 typedef long long LL;
     7 const LL mod = 1e9+7;
     8 const int maxn = 100005;
     9 LL n,a[maxn],dp[maxn],f[maxn];
    10 int main()
    11 {
    12     ios::sync_with_stdio(false);
    13     while(scanf("%lld",&n)!=EOF){
    14         for(int i=1;i<=n;i++){
    15             scanf("%lld",&a[i]);
    16             dp[i] = 0;f[i] = 0;
    17         }
    18         dp[0] = 1;
    19         for(int i=1;i<=n;i++){
    20             if(!f[a[i]])
    21                 dp[i] = (dp[i-1]*2)%mod;
    22             else//因为是减法 所以取模时需要加上mod再取模
    23                 dp[i] = (dp[i-1]*2 - dp[f[a[i]] - 1] + mod)%mod;
    24             f[a[i]] = i;
    25         }
    26         printf("%lld
    ",dp[n]-1);//减去空集
    27     }
    28     return 0;
    29 }
  • 相关阅读:
    jscript 处理文件
    网页右键菜单制作小demo
    精通正则表达式(元字符)
    精通正则表达式(正则引擎)
    js动态加载脚本
    精通正则表达式(JavaScript)
    Flex帮助文档制作(ASDoc——html篇)
    Flex帮助文档制作(FAR——chm篇)
    最基础的发布服务小demo
    Flex帮助文档制作(ASDoc——注释篇1)
  • 原文地址:https://www.cnblogs.com/wangrunhu/p/9403875.html
Copyright © 2011-2022 走看看