zoukankan      html  css  js  c++  java
  • 打卡3

    CodeForces - 597C Subsequences

    一拿到这个题感觉很新颖,不过没啥思路。

    看了大家的题解,一个$O(n^2 imes k)$的做法还是能写一写,虽然过不了。

    因为本题所有数字是个全排列,我们设状态是$dp[i][j]$,表示长度为$i$的子序列,以$j$结尾的方案数。

    状态转移方程是:$dp[i][j]=sum_{t=1}^{j-1}dp[i-1][t]$。预处理所有$dp[1][j]$,为了保证$t$都在$j$前面,我们可以边读入边处理。

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 1e3 + 10;
    typedef long long ll;
    ll dp[12][maxn];
    int main()
    {
        int n, k; scanf("%d %d", &n, &k);
        memset(dp, 0, sizeof(dp));
        for(int p = 1; p <= n; p++)
        {
            int x;
            scanf("%d", & x);
            dp[1][x] = 1;
            for(int i = 1; i <= k + 1; i++)
            {
                for(int t = 1; t <= x - 1; t++)
                {
                    dp[i][x] += dp[i - 1][t];
                }
            }
        }
        ll ans = 0;
        for(int i = 1; i <= n; i++)
        {
            ans += dp[k + 1][i];
        }
        printf("%I64d
    ", ans);
        return 0;
    }
    Code

    这么大的复杂度显然是过不了的,那就想想怎么优化。

    我们观察到求和那一项求的是前缀和,所以我们可以用树状数组来维护,复杂度降为$O(n imes k imes logn)$。

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 1e5 + 10;
    typedef long long ll;
    ll dp[12][maxn];
    int n, k;
    void add(int id, int x, ll val)
    {
        while(x <= n)
        {
            dp[id][x] += val;
            x += (x & -x);
        }
    }
    ll sum(int id, int x)
    {
        ll res = 0;
        while(x > 0)
        {
            res += dp[id][x];
            x -= (x & -x);
        }
        return res;
    }
    int main()
    {
        scanf("%d %d", &n, &k);
        memset(dp, 0, sizeof(dp));
        for(int p = 1; p <= n; p++)
        {
            int x;
            scanf("%d", & x);
            add(1, x, 1);
            for(int i = 2; i <= k + 1; i++)
            {
                ll tmp = sum(i - 1, x - 1);
                add(i, x, tmp);
            }
        }
        ll ans = 0;
        ans = sum(k + 1, n);
        printf("%I64d
    ", ans);
        return 0;
    }
    Code

     

    15年CCPC有道类似题目:HDU 5542

    只不过需要离散化一下,但这道题所有数字可能有重复的,不过不影响最终结果,手推一下小数据就知道了。 

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 1e3 + 5;
    typedef long long ll;
    const ll mod = 1e9 + 7;
    ll dp[maxn][maxn];
    int maxv;
    void add(int id, int x, ll val)
    {
        while(x <= maxv)
        {
            dp[id][x] = (dp[id][x] + val) % mod;
            x += (x & -x);
        }
    }
    ll sum(int id, int x)
    {
        ll res = 0;
        while(x > 0)
        {
            res = (res + dp[id][x]) % mod;;
            x -= (x & -x);
        }
        return res;
    }
    int a[maxn];
    int dis[maxn];
    int main()
    {
        int T, kase = 0; scanf("%d", &T);
        while(T--)
        {
            int n, k;
            scanf("%d %d", &n, &k);
            for(int i = 1; i <= n; i++) scanf("%d", &a[i]), dis[i] = a[i];
            sort(dis + 1, dis + n + 1);
            for(int i = 1; i <= n; i++)
            {
                a[i] = lower_bound(dis + 1, dis + n + 1, a[i]) - dis;
                maxv = max(a[i], maxv);
            }
            for(int i = 1; i <= n; i++)
            {
                for(int j = 1; j <= maxv; j++)
                {
                    dp[i][j] = 0;
                }
            }
            for(int p = 1; p <= n; p++)
            {
                add(1, a[p], 1);
                for(int i = 2; i <= k; i++)
                {
                    ll tmp = sum(i - 1, a[p] - 1);
                    add(i, a[p], tmp);
                }
            }
            ll ans = 0;
            ans = sum(k, maxv);
            printf("Case #%d: %I64d
    ", ++kase, ans);
        }
        return 0;
    }
    Code

    Hills And Valleys

     暑假这道DP,当时状态方程看了别人的也很难懂,现在再拿出来搞一搞。

    难受,晚上帮舍友做笔试题,好浪费时间,关键他面试不过……

    明天再做完吧……

  • 相关阅读:
    Linq&Lumbda
    PS颜色模式
    WPF绑定方式
    明三杰刘健
    齐有鲍叔,郑有子皮
    朱厚照
    管子&小白
    时间
    人外有人之神箭手养繇基篇
    楚共王
  • 原文地址:https://www.cnblogs.com/littlepear/p/9590225.html
Copyright © 2011-2022 走看看