zoukankan      html  css  js  c++  java
  • HDU 4352 XHXJ's LIS

    传送门

    题目大意:

    求[l, r]中数位的最长上升序列恰好为k的数的个数。

    题目分析:

    首先要理解(o(nlogn))求LIS问题的思路,每次寻找第一个大于等于的数将其更改。
    设dp[pos][sta][k]表示第pos位,sta见后,加入k是为了初始化减少后面的时间。
    sta表示前pos位的LIS,是一个2进制数,110位表示09是否被选,比如现在状态是0010100000,就是说LIS是2,4,分两种情况:

    • 现在加入一个数字3,用LIS的方法找到第一个大于等于3的数----4,将其置为0,并把3置为1,sat变为0011000000.
    • 若加入6,没有大于等于它的数,就直接将6置为1,sat变为0010101000
      需要先预处理to[i][j]表示i状态加入数字j后转移到的状态来加速。 我卡了半天T所以必须初始化。

    code

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    
    struct ioSys{
        inline ll read(){
            ll i = 0, f = 1; char ch = getchar();
            for(; (ch < '0' || ch > '9') && ch != '-'; ch = getchar());
            if(ch == '-') f = -1, ch = getchar();
            for(; ch >= '0' && ch <= '9'; ch = getchar())
                i = (i << 3) + (i << 1) + (ch - '0');
            return i * f;
        }
        inline void wr(int x){
            if(x < 0) putchar('-'), x = -x;
            if(x > 9) wr(x / 10);
            putchar(x % 10 + '0');
        }
        inline void operator >> (ll &x){
            x = read();
        }
        inline void operator << (int x){
            wr(x);
        }
    }IO;
    
    ll T;
    ll l, r, k, len;
    typedef long long ll;
    ll dp[25][1050][15], s[25], to[1050][15], oneNum[1050];
    
    inline void convert(ll x){
        len = 0;
        memset(s, 0, sizeof s);
        while(x) s[++len] = x % 10, x /= 10;
    }
    
    inline ll count(ll x){
        int ret = 0;
        while(x) ret++, x = x & (x - 1);
        return ret;
    }
    
    inline void init(){
        memset(dp, -1, sizeof dp);
        for(int i = 0; i <= (1 << 10) - 1; i++){
            for(int j = 0; j <= 9; j++){
                int  tmp = 0, p;
                for(p = j; p < 10; p++)
                    if(i & (1 << p)) break;
                if(p == 10) tmp = i | (1 << j);
                else tmp = i ^ (1 << p) | (1 << j);
                to[i][j] = tmp;
            }
        }
        for(int i = 0; i <= (1 << 10) - 1; i++)
            oneNum[i] = count(i);
    }
    
    inline ll DP(int pos, int sta, bool limit, bool lead, int K){
        if(!limit && !lead && dp[pos][sta][K] != -1) return dp[pos][sta][K];
        if(pos == 0) return oneNum[sta] == k || (lead && K == 1);
        int high = limit ? s[pos] : 9;
        ll ret = 0;
        for(int i = 0; i <= high; i++){
            if(i == 0 && lead) ret += DP(pos - 1, 0, limit && (i == high), true, K);
            else
                ret += DP(pos - 1, to[sta][i], limit && (i == high), false, K);
        }
        if(!limit && !lead) dp[pos][sta][K] = ret;
        return ret;
    }
    
    int main(){
       T = IO.read();
       init();
       for(int t = 1; t <= T; t++){
           IO >> l, IO >> r, IO >> k;
           convert(r);
           ll ret1 = DP(len, 0, 1, 1, k);
           convert(l - 1);
           ll ret2 = DP(len, 0, 1, 1, k);
           printf("Case #%d: %I64d
    ", t, ret1 - ret2);
       }
       return 0;
    }
    
    
  • 相关阅读:
    2、容器初探
    3、二叉树:先序,中序,后序循环遍历详解
    Hebbian Learning Rule
    论文笔记 Weakly-Supervised Spatial Context Networks
    在Caffe添加Python layer详细步骤
    论文笔记 Learning to Compare Image Patches via Convolutional Neural Networks
    Deconvolution 反卷积理解
    论文笔记 Feature Pyramid Networks for Object Detection
    Caffe2 初识
    论文笔记 Densely Connected Convolutional Networks
  • 原文地址:https://www.cnblogs.com/CzYoL/p/7662090.html
Copyright © 2011-2022 走看看