zoukankan      html  css  js  c++  java
  • SDUSTOJ 1801 LIS2(最长上升子序列不同值的数量)

    Description

    给定一个长度为n的序列(n <= 100) ,给定m(m <= n),求该序列中有多少值不相同的长度为m的严格上升子序列。

    Input

    先输入一个T,表明下面会有几组数据。
    每组数据先输入一个n,m,表明数组大小和上升子序列长度。
    下面一行有n个数代表该数组,且 1<=a[i]<=n;

    Output

    输出为一行,只需输出上述要求的个数(结果对1000000009取余)。

    Sample Input

    4
    2 2
    1 2
    4 3
    1 2 4 4
    5 4
    1 2 3 5 4
    5 1
    1 1 1 2 2

    Sample Output

    1
    1
    2
    2
    思路:
    还是第三届山科校赛的题目
    这个题开两个二维dp数组,第二个是一个延时的dp
    也就是没有更新当前状态的dp
    再开一个一维数组记一下当前位置数字上次出现的位置
    如果上次出现过的话就减掉上一次的dp值去重
    dp[i][j]表示以值i为结尾长度为j的最长上升子序列的不同值的数量
    具体看代码吧。。
    /* ***********************************************
    Author        :devil
    Created Time  :2016/4/26 22:18:57
    ************************************************ */
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #include <vector>
    #include <queue>
    #include <set>
    #include <map>
    #include <string>
    #include <cmath>
    #include <stdlib.h>
    using namespace std;
    typedef long long LL;
    const int N=110;
    const int mod=1e9+9;
    LL dp[N][N],dp2[N][N];
    int a[N],b[N];
    int main()
    {
        //freopen("in.txt","r",stdin);
        int t,n,m;
        scanf("%d",&t);
        while(t--)
        {
            scanf("%d%d",&n,&m);
            for(int i=1; i<=n; i++)
                scanf("%d",&a[i]);
            memset(dp,0,sizeof(dp));
            memset(dp2,0,sizeof(dp2));
            memset(b,-1,sizeof(b));
            b[a[1]]=dp[a[1]][1]=1;
            for(int i=2;i<=n;i++)
            {
                dp[a[i]][1]=1;
                int mi=min(i,m);
                for(int k=2;k<=mi;k++)
                {
                    for(int j=1;j<a[i];j++)
                    {
                        dp[a[i]][k]+=dp[j][k-1];
                        if(dp[a[i]][k]>=mod) dp[a[i]][k]-=mod;
                    }
                    if(b[a[i]]!=-1)
                    {
                        dp[a[i]][k]-=dp2[a[i]][k];
                        if(dp[a[i]][k]<0) dp[a[i]][k]+=mod;
                    }
                    dp2[a[i]][k]=dp[a[i]][k];
                }
                b[a[i]]=i;
            }
            LL ans=0;
            for(int i=1;i<=n;i++)
                ans=(ans+dp[i][m])%mod;
            printf("%lld
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    前端切图:自制简易音乐播放器
    SEO那些事:一句代码一键分享网站
    POJ 2553 Tarjan
    POJ 2186 Tarjan
    POJ 1236 Tarjan算法
    POJ 1330 Tarjan LCA、ST表(其实可以数组模拟)
    POJ 1470 Tarjan算法
    POJ 1985 求树的直径 两边搜OR DP
    POJ 3687 拓扑排序
    POJ 3522 Kruskal
  • 原文地址:https://www.cnblogs.com/d-e-v-i-l/p/5436931.html
Copyright © 2011-2022 走看看